简体   繁体   English

Java:为什么即使在创建对象之后,JVM堆大小也没有差异

[英]Java : Why there is no difference in JVM Heap Size even after Object Creation

I am trying to find out how JVM Heap Size would differ with Object creation . 我试图找出JVM堆大小与对象创建的不同之处。

For example if you see my below program , i am creating 10000 String Objects with in a for loop , but still there is no difference in Heap Size on to my JVM Environment . 例如,如果您看到下面的程序,我将在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);

    }

}

The call to totalMemory just gives you the amount of memory that's reserved by the Java process. totalMemory的调用仅提供Java进程保留的内存量。 It doesn't mean that it's actively being filled by objects on the heap. 这并不意味着它正在被堆中的对象积极填充。 As the javadocs say, it is the total amount of memory available for current and future objects. 正如javadocs所说,它是当前和将来对象可用的内存总量。

In fact Java will prefer to request memory in large chunks from the underlying operating system, rather than having to call malloc (or equivalent) every time a new object is created. 实际上,Java宁愿从底层操作系统请求大块内存,而不是每次创建新对象时都必须调用malloc (或等效方法)。

If you want to keep track of the actual size of the heap, you can do this simply in realtime by using a tool such as JConsole/JVisualVM, or in much more detail by using a memory profiler. 如果要跟踪堆的实际大小,则可以使用JConsole / JVisualVM之类的工具简单地实时执行此操作,或者使用内存分析器进行更详细的操作。 If you want to do it programmatically, you'll need to register an agent for the complex stuff, but heap details are exposed through JMX. 如果要以编程方式进行操作,则需要为复杂的东西注册一个代理,但是堆详细信息通过JMX公开。 Have a look at the java.lang:Memory MBean's HeapMemoryUsage attribute (which is what JConsole uses to display the memory chart). 看一下java.lang:Memory MBean的HeapMemoryUsage属性(JConsole用于显示内存图表的属性)。

由于JIT没有副作用,因此它还可能优化整个for循环。

Two reasons: 两个原因:

  1. You are measuring the amount of memory reserved for the heap, not the sum of the sizes of live objects. 您正在测量为堆保留的内存量,而不是活动对象大小的总和。
  2. You don't keep references to the allocated strings anyway, so the JVM is free to garbage collect them whenever it wants. 无论如何,您都不保留对分配的字符串的引用,因此JVM可以随时随意对其进行垃圾回收。

Basically i wanted to know why we use Static Methods in Java. 基本上我想知道为什么我们在Java中使用静态方法。

Because static methods are simpler than instance methods. 因为静态方法比实例方法简单。

so my question is to save memory (from object creation ) we use static Methods ?? 所以我的问题是节省内存(通过对象创建),我们使用静态方法

No. You should code with purpose and only create things you actually need. 不。您应该有针对性地进行编码,并且仅创建实际需要的东西。 You create an instance when you need to, and don't create one when you don't. 您可以在需要时创建实例,而在不需要时则不创建实例。 This is not for performance reasons but to reduce the conceptual weight of your code. 这不是出于性能原因,而是为了减少代码的概念量。 If you have to maintain your code, or some elses code, you need to find why is something being done and it takes alot longer to determine that pointless code really is pointless. 如果您必须维护您的代码或其他代码,则需要找出为什么要做某件事,并且要花很多时间才能确定毫无意义的代码确实毫无意义。 ie It takes longer to look for something which is not there, than something which is. 即,寻找不存在的东西比寻找不存在的东西需要更长的时间。


To support multi-threaded memory allocation, each thread has a thread local allocation buffer or TLAB . 为了支持多线程内存分配,每个线程都有一个线程本地分配缓冲区或TLAB

The free space only shows you how much is free in the common pool, but doesn't could the size available in each thread's TLAB. 可用空间仅显示公共池中有多少可用空间,而不能显示每个线程的TLAB中可用的空间。 If you allocate enough strings, you will see a sudden jump in memory usage as it loads another block. 如果分配足够的字符串,则在加载另一个块时,您会发现内存使用量突然增加。

What you can do is turn this off with -XX:-UseTLAB 您可以使用-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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM