系统相关
首页 > 系统相关> > java – 这个演示中的JVM内存分配和解除分配解释了什么?

java – 这个演示中的JVM内存分配和解除分配解释了什么?

作者:互联网

我有一个简单的演示来检查JVM内存分配和释放的详细信息.

Java版本

$java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

演示

/**
 * VM Options: -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 */
public class DefaultCollector {
    private static final int _1MB = 1024 * 1024;
    public static void main(String... args) {
        byte[] arr1 = new byte[2 * _1MB];
        byte[] arr2 = new byte[2 * _1MB];
        byte[] arr3 = new byte[2 * _1MB];
        byte[] arr4 = new byte[4 * _1MB];
    }
}

GC日志

[GC (Allocation Failure) [PSYoungGen: 6516K->695K(9216K)] 6516K->4791K(19456K), 0.0019189 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 9216K, used 7408K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 81% used [0x00000000ff600000,0x00000000ffc8e6a8,0x00000000ffe00000)
  from space 1024K, 67% used [0x00000000ffe00000,0x00000000ffeadcb0,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000020,0x00000000ff600000)
 Metaspace       used 3273K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 357K, capacity 392K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:38815', transport: 'socket'

我的问题

> -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio = 8已经设置,而eden – 8M,从 – 1M,到 – 1M清楚显示,为什么PSYoungGen总计9216K而不是10240K?
>为什么分配失败,因为Tenured和-XX:+HandlePromotionFailure中仍有空格应该是默认的,因为JDK 6及以后已经存在?
>为什么PSYoungGen:6516K-> 695K(9216K)因为这三个阵列在Young Generation中还活着?是因为分配失败了吗?
>为什么Metaspace占用这么多内存Metaspace使用3273K?究竟是什么,如果不只是类型信息?

我也试过其他组合:

>尺寸:1,1,1,4 =>伊甸园70%,终身40%

为什么?不应该全部在伊甸园吗?
>尺寸:1,1,1,1 =>伊甸园80%(约6M),终身0%

为什么80%(约6M)而不是伊甸园中的4M?

更新

在@Stephen C的帮助下,我发现在IntelliJ终端登录之前有一个输出

/usr/lib/jvm/java-8-oracle/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:42103,suspend=y,server=n -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -javaagent:/home/hearen/Downloads/idea-IU-183.5429.30/lib/rt/debugger-agent.jar -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/hearen/git/personal/about-java/target/classes:/usr/lib/jvm/java-8-oracle/lib/dt.jar:/usr/lib/jvm/java-8-oracle/lib/tools.jar:/usr/lib/jvm/java-8-oracle/lib/sa-jdi.jar:/usr/lib/jvm/java-8-oracle/lib/jconsole.jar:/usr/lib/jvm/java-8-oracle/lib/packager.jar:/usr/lib/jvm/java-8-oracle/lib/javafx-mx.jar:/usr/lib/jvm/java-8-oracle/lib/ant-javafx.jar:/home/hearen/.m2/repository/org/projectlombok/lombok/1.16.20/lombok-1.16.20.jar:/home/hearen/.m2/repository/junit/junit/4.11/junit-4.11.jar:/home/hearen/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/home/hearen/.m2/repository/cglib/cglib/3.2.4/cglib-3.2.4.jar:/home/hearen/.m2/repository/org/ow2/asm/asm/5.1/asm-5.1.jar:/home/hearen/.m2/repository/org/apache/ant/ant/1.9.6/ant-1.9.6.jar:/home/hearen/.m2/repository/org/apache/ant/ant-launcher/1.9.6/ant-launcher-1.9.6.jar:/home/hearen/Downloads/idea-IU-183.5429.30/lib/idea_rt.jar jvm.allocation.DefaultCollector

然后我手动使用CLI编译并运行程序

$javac DefaultCollector.java 
$java -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 DefaultCollector

输出然后变成

Heap
 PSYoungGen      total 9216K, used 6815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 83% used [0x00000000ff600000,0x00000000ffca7ff8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
 Metaspace       used 2464K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 265K, capacity 386K, committed 512K, reserved 1048576K

显然,大阵列4M直接进入Tenured,而另外三个2M分配给Young给我们上述结果.

解决方法:

我怀疑大部分内容都可以通过JVM中的“其他内容”来解释.

输出的最后一行是证明你有一个连接到JVM的代理.

Disconnected from the target VM, address: '127.0.0.1:38815', transport: 'socket'

AFAIK,代理将导致JVM加载,编译等应用程序不直接使用的类.然后代理将为套接字,缓冲区等分配堆对象以处理监视.

这将膨胀常规堆和元空间使用.

我建议您在没有连接代理的情况下从shell /命令行重复此实验.通过命令行选项打开GC记录来获取GC统计数据.

你的更新.

Apparently the big array 4M is directly into the Tenured while the other three 2M allocated in Young giving us the above results.

正确.有一个阈值,超过该阈值,对象直接分配到终身空间.它可以调整….

标签:java,jvm,garbage-collection,jvm-hotspot,java-8
来源: https://codeday.me/bug/20190607/1193575.html