【问题标题】:Java : Why there is no difference in JVM Heap Size even after Object CreationJava:为什么即使在创建对象之后 JVM 堆大小也没有差异
【发布时间】:2012-06-14 15:18:40
【问题描述】:

我试图找出 JVM 堆大小与对象创建有何不同。

例如,如果您看到我下面的程序,我在 for 循环中创建了 10000 个字符串对象,但在我的 JVM 环境中的堆大小仍然没有区别。

public class One {

    public static void main(String args[]) {

        long heapSizebefore = Runtime.getRuntime().totalMemory();
        System.out.println("heapSizebefore" + heapSizebefore);

        for (int i = 0; i <= 10000; i++) {
            String str = new String();

        }

        long heapSizeafter = Runtime.getRuntime().totalMemory();
        System.out.println("heapSizeafter" + heapSizeafter);

    }

}

【问题讨论】:

  • 大多数 OO 程序使用大量成员方法,因为您无法访问成员变量或使用静态方法实现接口。但是如果你不需要做这些事情,那么静态方法是有意义的。它告诉调用者“我只是一个函数;我不需要一个对象来做任何事情”。然而,没有理由仅仅因为内存而使方法成为静态的——你可能最终只是创建了一个对象作为参数传递,所以没有节省。
  • 如果你想知道我们为什么在 Java 中使用静态方法,为什么不问那个问题呢?或者更好,想想问它,然后搜索“java静态方法”,然后阅读manymanyduplicatesofit之一。
  • 请注意,按照这些思路,我已经删除了您询问静态方法的部分问题。 StackOverflow 每个问题只有一个问题,效果更好,恕我直言,这个页面现在是一个更好的例子,一个具体的、可搜索的问题和一个有效的答案。如果您想就现有问题未涵盖的静态方法提出问题,请随意创建一个新方法。

标签: java


【解决方案1】:

totalMemory 的调用只会为您提供Java 进程保留的内存量。这并不意味着它正在被堆上的对象主动填充。正如javadocs 所说,它是当前和未来对象的可用内存总量。

事实上,Java 更愿意从底层操作系统请求大块内存,而不是每次创建新对象时都必须调用 malloc(或等效项)。

如果您想跟踪堆的实际大小,可以使用 JConsole/JVisualVM 等工具简单地实时执行此操作,或者使用内存分析器更详细地执行此操作。如果您想以编程方式执行此操作,则需要为复杂的东西注册一个代理,但堆详细信息通过 JMX 公开。查看java.lang:Memory MBean 的HeapMemoryUsage 属性(JConsole 使用它来显示内存图表)。

【讨论】:

    【解决方案2】:

    JIT 也可能会优化整个 for 循环,因为它没有副作用。

    【讨论】:

      【解决方案3】:

      两个原因:

      1. 您正在测量为堆保留的内存量,而不是活动对象大小的总和。
      2. 无论如何您都不会保留对已分配字符串的引用,因此 JVM 可以随时对它们进行垃圾收集。

      【讨论】:

        【解决方案4】:

        基本上我想知道为什么我们在 Java 中使用静态方法。

        因为静态方法比实例方法简单。

        所以我的问题是节省内存(从对象创建)我们使用静态方法??

        没有。你应该有目的地编码,只创建你真正需要的东西。需要时创建实例,不需要时不要创建实例。这不是出于性能原因,而是为了减少代码的概念权重。如果您必须维护您的代码或其他一些代码,您需要找出为什么要做某事,并且需要更长的时间才能确定无意义的代码确实是无意义的。即寻找不存在的东西比寻找存在的东西要花更长的时间。


        为支持多线程内存分配,每个线程都有一个线程本地分配缓冲区或TLAB

        可用空间仅显示公共池中有多少可用空间,但不能显示每个线程的 TLAB 中可用的大小。如果你分配了足够多的字符串,你会在加载另一个块时看到内存使用量突然增加。

        你可以用-XX:-UseTLAB关闭它

        // -XX:+UseTLAB heapUsedBefore: 5,368,848 heapUsedAfter: 5,368,848
        // -XX:-UseTLAB heapUsedBefore: 535,048 heapUsedAfter: 535,096
        
        public class One {
            public static void main(String... args) {
                Runtime runtime = Runtime.getRuntime();
                long heapUsedBefore = runtime.totalMemory() - runtime.freeMemory();
        
                String str = new String();
        
                long heapUsedAfter = runtime.totalMemory() - runtime.freeMemory();
                System.out.printf("heapUsedBefore: %,d heapUsedAfter: %,d%n", 
                                   heapUsedBefore, heapUsedAfter);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2016-09-04
          • 2012-05-02
          • 1970-01-01
          • 1970-01-01
          • 2021-01-25
          • 2019-04-16
          • 1970-01-01
          • 1970-01-01
          • 2011-11-25
          相关资源
          最近更新 更多