如何在Java中强制垃圾收集?

如何在Java中强制垃圾收集?,java,garbage-collection,Java,Garbage Collection,在Java中强制垃圾收集是可能的,即使这很棘手吗?我知道System.gc()和Runtime.gc()但他们只建议执行GC。如何强制GC?您最好的选择是调用它,这只是提示垃圾收集器您希望它执行收集。由于垃圾收集器是不确定的,因此无法强制和立即收集。最好描述一下需要垃圾收集的原因。如果您使用的是SWT,则可以配置Image和Font等资源来释放内存。例如: Image img = new Image(Display.getDefault(), 16, 16); img.dispose(); 也

在Java中强制垃圾收集是可能的,即使这很棘手吗?我知道
System.gc()
Runtime.gc()但他们只建议执行GC。如何强制GC?

您最好的选择是调用它,这只是提示垃圾收集器您希望它执行收集。由于垃圾收集器是不确定的,因此无法强制和立即收集。

最好描述一下需要垃圾收集的原因。如果您使用的是SWT,则可以配置
Image
Font
等资源来释放内存。例如:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

<>也有一些工具来确定未处理的资源。

如果你需要强制收集垃圾,也许你应该考虑你是如何管理资源的。您正在创建在内存中持久存在的大型对象吗?您是否正在创建具有

一次性接口的大型对象(例如图形类),并且在使用该接口时未调用
dispose()
?您是否在类级别声明了仅在单个方法中需要的东西?

文档下声明,除非VM在完全垃圾收集后无法回收内存,否则不会抛出它。因此,如果您一直在分配内存直到出现错误,那么您将已经强制执行了完整的垃圾收集


大概你真正想问的问题是“我如何才能通过垃圾收集回收我认为应该回收的内存?”

.gc是未来版本中可能被淘汰的一个选项-一位Sun工程师曾经评论说,世界上实际知道如何使用的人可能不到二十人。gc()-我昨晚使用SecureRandom生成的数据在一个中心/关键数据结构上做了几个小时的工作,在刚刚超过40000个对象的某个位置,虚拟机会减速,好像指针用完了一样。显然,它被16位指针表阻塞,并表现出典型的“故障机器”行为

我尝试了-Xms等等,一直在旋转直到它运行到57xxx左右。然后,它将在gc()之后运行gc,从57127到57128,大约与camp Easy Money的代码膨胀速度相同

您的设计需要基本的重新工作,可能是滑动窗口方法

强制GC的最佳(如果不是唯一)方法是编写自定义JVM。我相信垃圾收集器是可插入的,所以您可能只需要选择一个可用的实现并对其进行调整

注意:这不是一个简单的答案


真的,我不明白你的意思。但是 清楚“无限对象创建” 我的意思是有一块 我的大系统中的代码可以创建 处理并在其中活动的对象 记忆,我找不到这张照片 代码实际上,只是手势

这是正确的,只是一种姿态。你已经有了几张海报上给出的标准答案。让我们一个接一个地看一下:

  • 我找不到这段代码 实际上
  • 正确,没有实际的jvm-这只是一个规范,一堆描述期望行为的计算机科学。。。我最近深入研究了从本机代码初始化Java对象。要想得到你想要的,唯一的方法就是进行所谓的主动置零。如果做错了,那么这些错误就是非常糟糕的行为,我们必须将自己限制在问题的原始范围内:

  • 我的大系统中的一些代码 创建对象
  • 这里的大多数海报都会假设你说你正在处理一个界面,如果这样的话,我们将不得不看看你是在一次处理整个对象还是一个项目

    如果不再需要对象,可以为该对象指定null,但如果错误,则会生成null指针异常。我敢打赌,如果你使用NIO,你可以获得更好的工作

    任何时候,你、我或其他任何人都会说:“拜托,我非常需要它。”这几乎是你正在努力工作的东西几乎完全毁灭的普遍前兆。。。。给我们写一个小的示例代码,从中清理任何实际使用的代码,并向我们展示您的问题

    不要沮丧。通常情况下,这会导致dba使用在某处购买的软件包,并且原始设计没有针对海量数据结构进行调整


    这是很常见的。

    如果内存不足,并且出现
    OutOfMemoryException
    异常,您可以尝试通过使用
    java-Xms128m-Xmx512m
    而不是仅使用
    java
    启动程序来增加java可用的堆空间量。这将为您提供128Mb的初始堆大小和512Mb的最大值,这远远超过标准的32Mb/128Mb。您可以对对象使用一个巧妙的小技巧强制垃圾收集

    从jlibs:

       /**
        * This method guarantees that garbage collection is
        * done unlike <code>{@link System#gc()}</code>
        */
       public static void gc() {
         Object obj = new Object();
         WeakReference ref = new WeakReference<Object>(obj);
         obj = null;
         while(ref.get() != null) {
           System.gc();
         }
       }
    

    JVM规范没有具体说明垃圾收集。因此,供应商可以按照自己的方式自由地实现GC

    因此,这种模糊性导致了垃圾收集行为的不确定性。您应该检查JVM的详细信息,以了解垃圾收集方法/算法。此外,还有自定义行为的选项。

    FYI

    方法调用System.runFinalizersOnExit(true)保证终结器方法 在Java关闭之前调用。然而,这种方法本质上是不安全的 而且已经被弃用了。另一种方法是在方法中添加“shutdownhooks” Runtime.addShutdownHook

    Masarrat Siddiqui

    使用

    jvmtiError ForceGarbageCollection(jvmtiEnv* env)
    
    将“强制VM执行垃圾收集”。JVM TI是手动请求GC(而不是从System.GC()中)的一部分。

  • 转到JDK中的:bin文件夹,例如-C:\Program Files\Java\jdk1.6.0\u 31\bin
  • 打开jconsole.exe
  • 连接到所需的本地进程
  • 转到内存选项卡并单击执行GC

  • 您可以从命令行触发GC。这是你
    jdk1.7.0/bin/jcmd <pid> GC.run
    
    System.gc ();
    System.runFinalization ();
    
    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();
    
    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) { }
    
    }
    
    @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
    
    if (input.equalsIgnoreCase("gc")) {
        System.gc();
        result = "Just some GC.";
    }
    
    if (input.equalsIgnoreCase("runtime")) {
        Runtime.getRuntime().gc();
        result = "Just some more GC.";
    }
    
    public static void triggerFullGC() throws IOException, InterruptedException {
        String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        Process process = Runtime.getRuntime().exec(
                String.format("jmap -histo:live %s", pid)
        );
        System.out.println("Process completed with exit code :" + process.waitFor());
    }