关于Java垃圾回收,某个方法生成的垃圾对象在方法执行完后就不能回收了吗?

程序先执行一个start方法来占用大量内存,然后执行endEmpty一直调用System.gc()
运行后,在任务管理器能看到程序的内存占用马上就达到了4G, 但是start方法出栈之后内存占用却一直不下降
这是正常的吗? 如何才能释放这些内存呢?

而且如果在start方法内调用System.gc(), 却能起作用, 这个方法到底什么时候有用什么时候无效...

    static final long BEGIN_MILLIS = System.currentTimeMillis();

    public static void main(String[] args) {
        HelloWorld h = new HelloWorld();
        h.start();
        h.endEmpty();
    }

    public void start() {
        System.out.println("start");
        ArrayList<Object> list = new ArrayList<Object>();
        while (System.currentTimeMillis() - BEGIN_MILLIS < TimeUnit.SECONDS.toMillis(10)) {
            list.add(System.getProperties().clone());
//            System.gc();
        }
    }

    public void endEmpty() {
        System.out.println("end");
        while (true) {
            System.gc();
        }
    }
阅读 4.4k
2 个回答

应该有两个原因:

  1. 即使java堆的内存回收了, 并不见得java会立刻把内存还给操作系统.
  2. System.gc() 不一定会触发gc操作.

另外, 监控java内存的使用情况最好使用 visualvm(jvisualvm) 或者 jstat 之类java提供的工具监控, 而不是操作系统提供的工具. 因为操作系统只是监控java程序本身申请了多少内存, 但是java申请了这么多内存并不见得一定会用这么多, 也不见得用完以后一定会换给操作系统.
具体可以了解下内存相关的配置.
给你看几张图吧:

clipboard.png

clipboard.png

clipboard.png
clipboard.png

我在一本书上看到的是这么说的,不知道能不能帮到你

垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题