最近在看周志明所著的《深入理解Java虚拟机》,有几个问题不太明白,希望对虚拟机有研究的哥们儿帮我解答一下。
先说一下我进行试验的环境:

操作系统:Mac OS X 10.11.6 EI Capitan

Java环境: java version "1.8.0_92"

Java(TM) SE Runtime Environment (build 1.8.0_92-b14)

Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

1. 我发现在年轻代中,即使我只是一个空类,没有进行任何的内存分配工作,Eden区域内存还是会被占用一部分,例子如下:

public class BlankedClassSize {

  public static void main(String[] args) {

  // TODO Auto-generated method stub
  }
}

虚拟机参数设置:

-verbose:gc -XX:+UseSerialGC -XX:+PrintGCDetails -Xmx20M -Xms20M -Xmn10M

虚拟机GC情况如下:

Heap

def new generation  total 9216K, used1164K
[0x00000007bf000000, 0x00000007bfa00000, 0x00000007bfa00000) eden space 8192K, 14% used [0x00000007bf000000, 0x00000007bf1231d0, 0x00000007bf800000) from space 1024K, 0% used [0x00000007bf800000, 0x00000007bf800000, 0x00000007bf900000) to space 1024K, 0% used [0x00000007bf900000, 0x00000007bf900000, 0x00000007bfa00000) tenured generation total 6144K, used 0K [0x00000007bfa00000, 0x00000007c0000000, 0x00000007c0000000) the space 6144K, 0% used [0x00000007bfa00000, 0x00000007bfa00000, 0x00000007bfa00200, 0x00000007c0000000) Metaspace used 2666K, capacity 4486K, committed 4864K, reserved 1056768K class space used 289K, capacity 386K, committed 512K, reserved 1048576K

问题1:这里是什么占用了内存?

2.当年轻代进行一次GC后,因为年轻代GC是采用复制算法收集内存的,那么正常情况下进行一次Minor GC后,Eden区域占存为什么不是零?是什么占用着内存?例子如下:

public class MinorGC {

    private static final int_1MB = 1024*1024;

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        testEdenGC();

    }

    public static void testEdenGC(){

        byte[] allocation1,allocation2,allocation3,allocation4,allocation5,allocation6;

        allocation1=newbyte[_1MB];

        allocation2=newbyte[_1MB];

        allocation3=newbyte[_1MB];

        allocation4=newbyte[_1MB];

        allocation5=newbyte[_1MB];

        allocation6=newbyte[_1MB];

    }

}

虚拟机参数设置:

-verbose:gc -XX:TenuringThreshold=1 -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRation=3 -XX:+PrintGCDetails -XX:+UseSerialGC

虚拟机GC情况:

[GC (Allocation Failure) DefNew: 6029K->1354K(8192K), 0.0032985 secs] 6029K->5450K(18432K), 0.0033216 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

def new generation   total 8192K, used 2440K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)

eden space 6144K,  17% used [0x00000007bec00000, 0x00000007bed0f748, 0x00000007bf200000)

from space 2048K,  66% used [0x00000007bf400000, 0x00000007bf5529b0, 0x00000007bf600000)

to   space 2048K,   0% used [0x00000007bf200000, 0x00000007bf200000, 0x00000007bf400000)

tenured generation   total 10240K, used 4096K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)

the space 10240K,  40% used [0x00000007bf600000, 0x00000007bfa00040, 0x00000007bfa00200, 0x00000007c0000000)

Metaspace       used 2666K, capacity 4486K, committed 4864K, reserved 1056768K

class space    used 289K, capacity 386K, committed 512K, reserved 1048576K

问题2:根据6026K->1354K(8192K)可知,进行GC后,allocation1转入survivor1,allocation2~4转入老年区,此时eden中还有1354K内存被占用,是什么占用的?根据6029K->5450K(18432K),知道GC后,Java堆内存减少了579K,减少的这部分是谁的内存(明显新建的几个对象都可达,不至于被回收)?

3. 当给新对象分配内存的时候,因为年轻代空间不足,会发生一次minor GC,将年轻代中依然存活的对象复制到老年区,给新对象腾出空间,根据我的实验,此时若老年区内存不够将年轻代对象复制过去但是够新对象的存储,(此时会发生担保失败)则会直接将新对象放进老年代,例子如下:

public class MinorGC {

  private static  final int_1MB = 1024*1024;

  public static void main(String[] args) {

    // TODO Auto-generated method stub

    testAllocation();
  }   public static void testAllocation(){     byte[] allocation1,allocation2,allocation3,allocation4;     allocation1 = newbyte[2*_1MB];     allocation2 = newbyte[2*_1MB];     allocation3 = newbyte[2*_1MB];     allocation4 = newbyte[4*_1MB];   }
}

虚拟机参数设置如下:

-verbose:gc -Xms16M -Xmx16M -Xmn10M -XX:+PrintGCDetails  -XX:SurvivorRatio=8  -XX:+HeapDumpOnOutOfMemoryError -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC

GC情况如下:

[GC (Allocation Failure) [DefNew (promotion failed) : 7144K->7474K(9216K), 0.0028055 secs][Tenured: 4096K->4096K(6144K), 0.0015627 secs] 7144K->6473K(15360K), [Metaspace: 2660K->2660K(1056768K)], 0.0044048 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

def new generation   total 9216K, used 6555K [0x00000007bf000000, 0x00000007bfa00000, 0x00000007bfa00000)

eden space 8192K,  80% used [0x00000007bf000000, 0x00000007bf666ed0, 0x00000007bf800000)

from space 1024K,   0% used [0x00000007bf900000, 0x00000007bf900000, 0x00000007bfa00000)

to   space 1024K,   0% used [0x00000007bf800000, 0x00000007bf800000, 0x00000007bf900000)

tenured generation   total 6144K, used 4096K[0x00000007bfa00000, 0x00000007c0000000, 0x00000007c0000000)

the space 6144K,  66% used [0x00000007bfa00000, 0x00000007bfe00020, 0x00000007bfe00200, 0x00000007c0000000)

Metaspace       used 2666K, capacity 4486K, committed 4864K, reserved 1056768K

class space    used 289K, capacity 386K, committed 512K, reserved 1048576K

根据上面输出结果,可以看出,GC过程中,年轻代7144K->;7144K(9216K),并没有将年轻代中的对象转移走,而老年代中4096K->4096K(6144K),tenured generation   total 6144K, used 4096K,说明allocation4直接被转移到老年代中了。

问题3:难道这种情况下虚拟机会自动设置大对象阈值??将新对象直接放入老年去?

以上三个问题让我这个虚拟机小白百思不得其解,还希望大家帮我解释一下,在此谢过。

小白请教几个关于Java虚拟机内存分配策略的问题的更多相关文章

  1. 深入理解java虚拟机---内存分配策略(十三)

    转载请注明原文地址:https://blog.csdn.net/initphp/article/details/30487407 Java内存分配策略 使用的ParNew+Serial Old收集器组 ...

  2. JAVA虚拟机内存分配与回收机制

    Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现.Java虚拟机有自己想象中的硬件,如处理器.堆栈.寄存器等 ...

  3. java中内存分配策略及堆和栈的比较

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  4. Java虚拟机内存分配详解

    简介 了解Java虚拟机内存分布的好处 1.了解Java内存管理的细节,有助于程序员编写出性能更好的程序.比如,在新的线程创建时,JVM会为每个线程创建一个专属的栈 (stack),其栈是先进后出的数 ...

  5. Java虚拟机内存分配与回收策略

    内存分配与回收策略 Minor GC 和 Full GC Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行, 执行的速度一般也会比较快. Full GC ...

  6. 深入理解Java虚拟机-内存分配与回收策略

    一.内存分配策略 新生代中98%的对象都是"朝生夕死"的,所以并不需要按照1:1的比例来划分内存空间,而是将内存(新生代内存)分为一块较大的Eden(伊甸园)空间和两块较小的Sur ...

  7. 理解java虚拟机内存分配堆,栈和方法区

    栈:存放局部变量 堆:存放new出来的对象 方法区:存放类的信息,static变量,常量池(字符串常量) 在堆中,可以说是堆的一部分   创建了一个student类,定义了name属性, id静态变量 ...

  8. Java的内存分配策略

    简单来说,对象内存分配主要是在堆中分配.但是分配的规则并不是固定的,取决于使用的收集器组合以及JVM内存相关参数的设定 以下介绍几条基本规则(使用的ParNew+Serial Old收集器组合): 一 ...

  9. Java虚拟机内存分配和回收策略

    1 对象优先分配在Eden区 对象优先在Eden进行分配,大多数情况下,对象在新生代Eden区进行分配.当Eden区没有足够的空间进行分配时,虚拟机会发起一次Minor GC. 新生代GC(Ninor ...

随机推荐

  1. 设置height:100%无效的解决方法

    设置height:100%无效的解决方法 刚接触网页排版的新手,常出现这种情况:设置table和div的高height="100%"无效,使用CSS来设置height:" ...

  2. mysql 创建存储过程报错

    在创建存储过程前把结束符定义为 delimiter // 然后再创建就不会报错

  3. Table 表单样式

    <style> table th { white-space: nowrap; background-color: #f5f5f5; height:30px; font-size:14px ...

  4. RabbitMQ学习系列(五): RPC 远程过程调用

    前面讲过一些RabbitMQ的安装和用法,也说了说RabbitMQ在一般的业务场景下如何使用.不知道的可以看我前面的博客,http://www.cnblogs.com/zhangweizhong/ca ...

  5. java内存区域简介

    运行时数据区域 1.程序计数器:是一块较小的内存空间,可以看做当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理. ...

  6. 记录分享公司Spring data相关配置

    起因 公司Spring Data相关的配置还是有点意思的,不过蛮复杂的...XML很多...我不太喜欢强行记住....所以我打算记录一下配置的大致思路和结构,以后可能会有用.... 总体结构 总体结构 ...

  7. 一道Apple公司(中国)的面试题目

    Apple在中国(上海)有公司业务,但是感觉主要是做测试工作的部门,主要是保障Apple的产品质量QE.面试的时候,面试官出了一道题目,我貌似曾今开过类似的题目,但是由于当场发挥不佳没有答出来.题目大 ...

  8. 【bzoj1688】[USACO2005 Open]Disease Manangement 疾病管理

    题目描述 Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) is running through the farm. Far ...

  9. AD域的安装(在Windows Server 2003中安装Active Directory)

    在Active Directory中提供了一组服务器作为身份验证服务器或登录服务器,这类服务器被称作域控制器(Domain Controller,简称DC).建立一个AD域的过程实际就是在一台运行Wi ...

  10. runtime 第四部分method swizzling

    接上一篇 http://www.cnblogs.com/ddavidXu/p/5924597.html 转载来源http://www.jianshu.com/p/6b905584f536 http:/ ...