最近我一直在阅读Java不同世代的对象分配。大多数时候,新对象在伊甸园(年轻一代的一部分)中分配,然后如果满足以下任何标准,它们就会晋升为老一代。
(1) 当从伊甸园(或)另一个幸存者空间(从)复制对象时,对象的年龄已达到寿命阈值
(2)幸存者空间(到)已满
但是也有一种特殊情况,即对象直接在旧一代中分配,而不是从年轻一代中提升。当我们试图创建的对象很大(可能是几个MB的数量级)时,就会发生这种情况。
有没有办法知道这些巨大物体的大小/极限?我知道G1垃圾收集器的庞大对象标准。我只想知道Java 6之前或中的大小限制。
感谢您抽出时间:)
JVM标志:
-Xms1G-Xmx1G-Xmn500m-XX:PreforureSizeThreshold=100000000-XX:PrintGCDetails
通过将年轻一代的大小固定为500MB,eden大约有384MB,因此任何大于384MB的对象都直接进入OldGen,而小于384MB的对象则在eden中分配。你可以在下面找到这一代人的用法
字节[]数组=新字节[400*1024*1024];
PSYoungGen total 448000K, used 30720K
eden space 384000K, 8% used
from space 64000K, 0% used
to space 64000K, 0% used
ParOldGen total 536576K, used 409600K
object space 536576K, 76% used
字节[]数组=新字节[300*1024*1024];
PSYoungGen total 448000K, used 337920K
eden space 384000K, 88% used
from space 64000K, 0% used
to space 64000K, 0% used
ParOldGen total 536576K, used 0K
object space 536576K, **0% used**
对于400MB分配,eden使用率为8%,而旧gen使用率为76%对于300MB分配,eden使用率为88%,而旧gen使用率为0%因此很明显,所有大小大于eden的对象都将直接分配到旧gen中。
谢谢阿潘金
您可以使用以下标志设置限制
XX:PretenureSizeThreshold=size
它的默认值是0
我假设默认情况下,如果您不设置它,它不会被考虑为value=0
,这意味着默认情况下没有充当阈值的最大值,默认情况下,对象仅根据GC存活的数量得到提升
热点版本
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
要获得所有vm选项(受支持),您可以运行
java -XX:+PrintVMOptions -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version
然后你可以参考热点虚拟机选项文档或谷歌特定选项(如果没有列出)
byte[] array = new byte[300*1024*1024];
for(MemoryPoolMXBean memoryPoolMXBean: ManagementFactory.getMemoryPoolMXBeans()){
System.out.println(memoryPoolMXBean.getName());
System.out.println(memoryPoolMXBean.getUsage().getUsed());
}
输出:
$ java -Xmx1500m -Xms1500m -Xmn500m -XX:PretenureSizeThreshold=100000000 -XX:+PrintGCDetails JVMMemoryInspection
Code Cache
393664
PS Eden Space
330301752
PS Survivor Space
0
PS Old Gen
0
PS Perm Gen
2749520
年轻一代JVM可能分配的最大对象大小几乎与Eden(年轻一代减去两个幸存者空间)的大小一样大。
这就是分配rougly的样子:
tlab_top
size
我有这个程序: 我期望看到的是在年轻一代中创建整数对象,其中一些对象添加到转移到老一代的链表中。所以我希望年轻一代的GC能够始终如一地发生,对象被移动到生存空间,然后再从那里移动到老一代。但我发现的是,老一代的GC一直在发生,年轻一代的GC根本没有发生。这是JVM正在做的某种优化吗?在旧代中直接创建对象的地方?正如您在下图中看到的,年轻的gc只发生了两次,而老的gc发生了41次。仅旧代GC 接下来
问题内容: 我希望能够直接调用分配给对象属性的闭包,而无需将闭包重新分配给变量然后再调用它。这可能吗? 下面的代码不起作用,并导致。 问题答案: 从PHP7开始,您可以 或使用Closure ::call(),尽管不适用于。 在PHP7之前,您必须实现magic 方法来拦截调用并调用回调(当然不可能,因为您无法添加该方法) 请注意,您不能做 在体内,因为这会触发无限循环。
我正在为max分配8GB内存给Java编写的应用程序。它会内存溢出。我相信年轻一代总是比默认情况下的老一代小(堆的1/4)。而Eden/幸存者1,2在年轻一代内部。我相信在Eden空间中创建了新对象。 即使老一代还没有满,但年轻一代已经完全满了,java应用程序还是会耗尽内存吗? 如果短寿命的对象比长寿命的对象多,那么可以为年轻一代分配更多内存,或者至少将堆的50%分配给年轻一代吗?或者,由于jv
问题内容: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代?(我猜想在我认为的时间内,它很可能会降落到旧的gen中。)如果在perm gen中分配了它,那么当在Perm Gen中进行类卸载时,是否会收集垃圾? 问题答案: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代? 变量引用的对象将根据与其他任何对象相同的规则进行分配。它最有可能在年轻一代或老一代中分配(如果它很大,并且适用某
问题内容: 我多次听说,在实例化对象时应该执行以下操作: “接口”名称=新的“类”(); 例如,针对实现的类链表: 实现许多接口,包括队列,双端队列等。上面的代码和 要么 为什么必须同时指定两次类型?似乎多余,但oracledocs似乎没有提及。 问题答案: 在Java 7中是多余的。可以将其重写为。 你想写类似的原因: 如果您改变主意,则可以为您提供以后更改数据收集的自由。这样,您的代码将更加灵
我的问题是: > 如何使其与较大的文件一起工作? 有什么办法能让它快一点吗? 我的电脑有8GB的RAM,运行64位Windows 7,处理器是3.40GHz(不确定你需要什么信息)。