我试图找出JVM堆大小与对象创建的不同之处。
例如,如果您看到我的下面的程序,我在for循环中创建了10000个String对象,但是我的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);
}
}
答案 0 :(得分:4)
对totalMemory
的调用只会为您提供Java进程保留的内存量。这并不意味着它正在被堆上的对象主动填充。正如javadocs所说,它是当前和未来对象的可用内存总量。
事实上,Java更愿意从底层操作系统请求大块内存,而不是每次创建新对象时都必须调用malloc
(或等效)。
如果要跟踪堆的实际大小,可以使用JConsole / JVisualVM等工具实时完成此操作,或者使用内存分析器更详细地实现。如果您想以编程方式执行此操作,则需要为复杂内容注册代理,但堆详细信息通过JMX公开。查看java.lang:Memory
MBean的HeapMemoryUsage
属性(JConsole用于显示内存图表的属性)。
答案 1 :(得分:2)
JIT也可能优化整个for
循环,因为它没有副作用。
答案 2 :(得分:2)
有两个原因:
答案 3 :(得分:0)
基本上我想知道为什么我们在Java中使用静态方法。
因为静态方法比实例方法简单。
所以我的问题是保存内存(来自对象创建)我们使用静态方法??
没有。你应该有目的地编码,只创造你真正需要的东西。您可以在需要时创建实例,而在不需要时不创建实例。这不是出于性能原因,而是为了减少代码的概念性重量。如果你必须维护你的代码或一些elses代码,你需要找到为什么要做的事情,并且需要更长的时间来确定无意义的代码真的没有意义。即,寻找不存在的东西需要更长的时间,而不是那些东西。
为了支持多线程内存分配,每个线程都有一个线程本地分配缓冲区或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);
}
}