是否有可能在Java中强制垃圾收集,即使这很棘手?我知道System.gc();和Runtime.gc ();但他们只建议做GC。如何强制GC?
当前回答
如果您正在运行内存并得到一个OutOfMemoryException,您可以尝试通过java -Xms128m -Xmx512m开始编程来增加java可用的堆空间的数量,而不仅仅是java。这将使您的初始堆大小为128Mb,最大堆大小为512Mb,远远超过标准的32Mb/128Mb。
其他回答
如果您正在运行内存并得到一个OutOfMemoryException,您可以尝试通过java -Xms128m -Xmx512m开始编程来增加java可用的堆空间的数量,而不仅仅是java。这将使您的初始堆大小为128Mb,最大堆大小为512Mb,远远超过标准的32Mb/128Mb。
如果您正在使用JUnit和Spring,请尝试在每个测试类中添加以下内容:
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
JVM规范没有详细说明垃圾收集。因此,供应商可以自由地以自己的方式实现GC。
因此,这种模糊性导致了垃圾收集行为的不确定性。您应该检查JVM的详细信息以了解垃圾收集方法/算法。此外,还有自定义行为的选项。
在OutOfMemoryError的文档中,它声明除非虚拟机在完整的垃圾回收后未能回收内存,否则它不会被抛出。因此,如果您一直分配内存直到出现错误,那么您将已经强制进行完整的垃圾收集。
想必您真正想问的问题是“如何回收我认为应该通过垃圾收集回收的内存?”
另一种选择是不创建新对象。
对象池是为了减少Java中对GC的需求。
对象池通常不会比对象创建快(特别是对于轻量级对象),但它比垃圾收集快。如果您创建10,000个对象,每个对象是16个字节。GC需要回收160,000个字节。另一方面,如果您不需要同时使用所有10,000个对象,您可以创建一个池来回收/重用对象,这样就不需要构造新对象,也不需要GC旧对象。
类似这样(未经测试)。 如果你想让它是线程安全的,你可以把LinkedList换成ConcurrentLinkedQueue。
public abstract class Pool<T> {
private int mApproximateSize;
private LinkedList<T> mPool = new LinkedList<>();
public Pool(int approximateSize) {
mApproximateSize = approximateSize;
}
public T attain() {
T item = mPool.poll();
if (item == null) {
item = newInstance();
}
return item;
}
public void release(T item) {
int approxSize = mPool.size(); // not guaranteed accurate
if (approxSize < mApproximateSize) {
recycle(item);
mPool.add(item);
} else if (approxSize > mApproximateSize) {
decommission(mPool.poll());
}
}
public abstract T newInstance();
public abstract void recycle(T item);
public void decommission(T item) { }
}
推荐文章
- Java 8接口方法中不允许“同步”的原因是什么?
- 如何找到Java堆大小和内存使用(Linux)?
- 使用Enum实现单例(Java)
- RabbitMQ与通道和连接之间的关系
- buildSessionFactory()配置方法在Hibernate中已弃用?
- Spring MVC -如何获得所有的请求参数在一个地图在Spring控制器?
- 如何在Java中按两个字段排序?
- 文件之间的差异。路径中的分隔符和斜杠
- 在方法参数中使用NotNull注释
- Spring MVC中处理可选参数的@RequestParam
- Tomcat:如何查找正在运行的Tomcat版本?
- “java”、“javaw”和“javaws”之间有什么区别?
- 将Date对象转换为日历对象
- 在Java中保存最后N个元素的大小有限的队列
- 如何运行一个类从Jar不是主类在其清单文件