是否有可能在Java中强制垃圾收集,即使这很棘手?我知道System.gc();和Runtime.gc ();但他们只建议做GC。如何强制GC?
当前回答
在OutOfMemoryError的文档中,它声明除非虚拟机在完整的垃圾回收后未能回收内存,否则它不会被抛出。因此,如果您一直分配内存直到出现错误,那么您将已经强制进行完整的垃圾收集。
想必您真正想问的问题是“如何回收我认为应该通过垃圾收集回收的内存?”
其他回答
在OutOfMemoryError的文档中,它声明除非虚拟机在完整的垃圾回收后未能回收内存,否则它不会被抛出。因此,如果您一直分配内存直到出现错误,那么您将已经强制进行完整的垃圾收集。
想必您真正想问的问题是“如何回收我认为应该通过垃圾收集回收的内存?”
FYI
方法调用System.runFinalizersOnExit(true)保证终结器方法 在Java关闭之前调用。然而,这种方法本质上是不安全的 并且已经被弃用。另一种方法是在方法中添加“关机钩子” Runtime.addShutdownHook。
马萨拉特·西迪基
有一些间接的方法来强制垃圾收集器。您只需要用临时对象填充堆,直到垃圾收集器执行为止。我已经创建了一个类,它以这样的方式强制垃圾收集器:
class GarbageCollectorManager {
private static boolean collectionWasForced;
private static int refCounter = 0;
public GarbageCollectorManager() {
refCounter++;
}
@Override
protected void finalize() {
try {
collectionWasForced = true;
refCounter--;
super.finalize();
} catch (Throwable ex) {
Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int forceGarbageCollection() {
final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
int iterationsUntilCollected = 0;
collectionWasForced = false;
if (refCounter < 2)
new GarbageCollectorManager();
while (!collectionWasForced) {
iterationsUntilCollected++;
int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
arr = null;
}
return iterationsUntilCollected;
}
}
用法:
GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();
我不知道这个方法有多有用,因为它不断地填充堆,但如果你有任务关键的应用程序必须强制GC -当这可能是Java强制GC的可移植方式。
真的,我不懂你。而是成为 清楚“无限物体创造” 我是说有一些 代码在我的大系统做创建 可以处理的对象,并在其中生活 回忆,我无法得到这一片 其实是代码,只是个手势!!
这是正确的,唯一的姿态。你已经有了很多标准答案。让我们一个一个来看:
我无法得到这段代码 实际上
正确,没有真正的jvm——这只是一个规范,一堆描述期望行为的计算机科学…我最近研究了如何从本地代码初始化Java对象。要得到你想要的东西,唯一的方法就是执行所谓的主动置空。如果做错了,错误是非常糟糕的,我们必须将自己限制在问题的原始范围内:
我大系统里的一段代码 创建对象
这里的大多数海报会假设你说你正在处理一个界面,如果是这样的话,我们就必须看看你是一次被交付整个对象还是一个项目。
如果你不再需要一个对象,你可以将null赋值给该对象,但如果你弄错了,就会生成一个空指针异常。我敢打赌,如果您使用NIO,您可以实现更好的工作
任何时候你或我或其他人得到:“拜托,我非常需要那个。”这几乎是一个普遍的前兆,几乎完全破坏你正在努力工作....写一个小的示例代码,从它消毒任何实际使用的代码,并向我们展示您的问题。
不要沮丧。通常情况下,这意味着您的dba正在使用从某个地方购买的包,并且原始设计没有针对大规模数据结构进行调整。
这很常见。
另一种选择是不创建新对象。
对象池是为了减少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) { }
}
推荐文章
- 为什么“System.out。”println“工作在Android?
- 在Java中什么时候使用可变参数?
- Mockito的argumentCaptor的例子
- 我如何告诉Spring Boot哪个主类用于可执行jar?
- 如何将Java8流的元素添加到现有的列表中
- 在Java 8中是否可以转换流?
- 不区分大小写的字符串作为HashMap键
- 什么是maven中的“pom”打包?
- 在Java中创建一个自定义事件
- 创建正则表达式匹配数组
- 我如何在Java中初始化一个全零的数组列表?
- 主体、使用者和主体之间的意义和区别是什么?
- 将字节转换为十六进制
- HashSet和HashMap的区别?
- 我如何有效地解析HTML与Java?