`
hz_chenwenbiao
  • 浏览: 995174 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JVM内存模型学习,记录(转)

    博客分类:
  • JVM
阅读更多

文章出处(引用):http://topic.csdn.net/u/20090602/10/bd9d4ba2-dbeb-49b3-8651-67c5de2b228a.html

 

 

如图所示,JVM主要包括两个子系统和两个组件。两个子系统分别是Class loader子系统Execution engine(执行引擎) 子系统;两个组件分别是Runtime data area (运行时数据区域)组件Native interface(本地接口)组件

 

Class loader子系统的作用:

根据给定的全限定名类名(如 java.lang.Object)来装载class文件的内容到 Runtime data area中的method area(方法区域)。Java程序员可以extends java.lang.ClassLoader类来写自己的Class loader。

 

Execution engine子系统的作用:

执行classes中的指令。任何JVM specification实现(JDK)的核心都是Execution engine,不同的JDK例如Sun 的JDK 和IBM的JDK好坏主要就取决于他们各自实现的Execution engine的好坏。

 

Native interface组件:

与native libraries交互,是其它编程语言交互的接口。当调用native方法的时候,就进入了一个全新的并且不再受虚拟机限制的世界,所以也很容易出现JVM无法控制的native heap OutOfMemory。

 

Runtime Data Area组件:

这就是我们常说的JVM的内存了。它主要分为五个部分——
1、Heap (堆):一个Java虚拟实例中只存在一个堆空间
2、Method Area(方法区域):被装载的class的信息存储在Method area的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。
3、Java Stack(java的栈):虚拟机只会直接对Java stack执行两种操作:以帧为单位的压栈或出栈
4、Program Counter(程序计数器):每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。PC寄存器的内容总是指向下一条将被执行指令的饿地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。  
5、Native method stack(本地方法栈):保存native方法进入区域的地址

以上五部分只有Heap 和Method Area是被所有线程的共享使用的;而Java stack, Program counter 和Native method stack是以线程为粒度的,每个线程独自拥有自己的部分

 

 

Sun的JVM Generational Collecting(垃圾回收)原理是这样的:把对象分为年青代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。(基于对对象生命周期分析)

如上图所示,为Java堆中的各代分布。  
1. Young(年轻代)
年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制年老区(Tenured。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。  
2. Tenured(年老代)
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。  
3. Perm(持久代)
用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。

举个例子:当在程序中生成对象时,正常对象会在年轻代中分配空间,如果是过大的对象也可能会直接在年老代生成(据观测在运行某程序时候每次会生成一个十兆的空间用收发消息,这部分内存就会直接在年老代分配)。年轻代在空间被分配完的时候就会发起内存回收,大部分内存会被回收,一部分幸存的内存会被拷贝至Survivor的from区,经过多次回收以后如果from区内存也分配完毕,就会也发生内存回收然后将剩余的对象拷贝至to区。等到to区也满的时候,就会再次发生内存回收然后把幸存的对象拷贝至年老区。

通常我们说的JVM内存回收总是在指堆内存回收,确实只有堆中的内容是动态申请分配的,所以以上对象的年轻代和年老代都是指的JVM的Heap空间,而持久代则是之前提到的Method Area,不属于Heap。

 

 

个参数意义:

引用:http://longdick.iteye.com/blog/468368

 

 

 

在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用。这部分内存大小由 -Xmx 参数指定。

 

而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用。影响这个的参数是 -Xms ,如果 -Xms 指定的值比-Xmx 的小,那么两者的差值就是Virtual内存值。随着程序的运行,Eden区、 Tenured区和Perm区会逐渐使用保留的Virtual空间。

 

如果没有具体指定,初始和最大堆内存将根据机器的内存计算得出。参数DefaultInitialRAMFraction DefaultMaxRAMFraction 会影响最终的结果,如下表所示:

 


Formula Default
initial heap size memory / DefaultInitialRAMFraction memory /64
maximum heap size MIN(memory / DefaultMaxRAMFraction, 1GB) MIN(memory/ 4, 1GB)

 

可以看到堆内存默认值最大不会超过1G。

 

JVM会根据堆内存的使用情况自动决定何时扩张和缩减实际堆内存的大小,可以用VM参数 -XX:MinHeapFreeRatio=<minimum> 和 -XX:MaxHeapFreeRatio=<maximum> 使用堆内存空闲百分比来定义,一般在32位机器上的默认值如下:

 

Parameter Default Value
MinHeapFreeRatio 40
MaxHeapFreeRatio 70
-Xms 3670k
-Xmx 64m

 

 

当空闲堆内存所占堆内存百分比低于40%,JVM就会试图扩张堆内存空间;当空闲堆内存所占堆内存百分比高于70%,JVM就会试图压缩堆内存空间。

ps:以上默认值在不同平台会有不同的值,如果是64位系统,这些值一般需要扩张30%,来容纳在64位系统下变大的对象。

 

加上-XX:NewRatio=3 意味着 young(年轻代) 和 tenured(终生代)的比率是1:3,也就是说,eden区和survivor区容量之和将占总堆内存的1/4。

 

加上-XX:SurvivorRatio=6 设置eden区和 其中一个survivor space的比率是1:6,也就是说,其中一个survivor space占年轻代1/8的容量 (可以想想为什么不是1/7)。

 

另外还有 -XX:NewSize  -XX:MaxNewSize   指定年轻代的初始值和最大值。

32位系统下默认值如下:

 


Default Value Parameter Client JVM Server JVM
NewRatio 8 2
NewSize 2228K 2228K
MaxNewSize not limited not limited
SurvivorRatio 32 32

 

分享到:
评论

相关推荐

    JVM内存模型fager20200614.docx

    在 HotSpot 虚拟机中,分为 3 块区域:对象头(Header)、实例数据...另外,如果是 Java 数组,对象头中还必须有一块用于记录数组长度的数据,因为普通对象可以通过 Java 对象元数据确定大小,而数组对象不可以。

    jvm开发知识

    Java虚拟机内存模型: 1、程序计数器,这个是线程私有的,各个线程之间的计数器是相互独立的,不相互影响的,计数器主要用于记录线程下条执行的程序指令;

    Java及大数据学习路线.pdf

    Nginx反向代理、负载均衡、动静分离 JVM内存模型、参数调优 JUC线程⾼级 分布式架构注册中⼼Zookeeper 虚拟化应⽤容器Docker 全⽂检索引擎ElasticSearch 消息队列RabbitMQ 前端VUE/ES6 2⼤数据学习路线 2.1JavaSE ...

    Sivyer9303.github.io

    MenuJVM jvm错误排查手段及工具 多线程及高并发 容器类 类加载机制 堆外内存 jvm内存模型Redis 持久化与主从同步 redis为什么高效 缓存雪崩、缓存穿透、缓存击穿 一致性hash 分布式锁 redis限流 高可用设计RocketMq ...

    javaOA办公系统模块设计方案.pdf

    服务器监控:实时监控jvm内存,服务器内存,CPU使⽤率。 单次读取服务器其它配置等信息 13. 接⼝测试:POST or GET ⽅式检测系统接⼝,参数加密,json返回结果,计算服务器响应时间 14.系统设置:修改系统名称,每页...

    java8源码-concurrency:java并发总结

    Java内存模型 1.8 可重入 1.9 偏向锁、轻量级锁、重量级锁 1.10 锁的公平性 1.11 线程组 2 多线程基本实现 2.1 多线程实现 Interface Runnable Callable Future ExecutorService Class Thread FutureTask FutureTask...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    6.1 关系数据库按主键区分不同的记录 123 6.1.1 把主键定义为自动增长标识符类型 123 6.1.2 从序列(Sequence)中获取自动增长的标识符 124 6.2 Java语言按内存地址区分不同的对象 125 6.3 Hibernate用对象...

    精通Hibernate:对象持久化技术第二版part3

    6.1 关系数据库按主键区分不同的记录 123 6.1.1 把主键定义为自动增长标识符类型 123 6.1.2 从序列(Sequence)中获取自动增长的标识符 124 6.2 Java语言按内存地址区分不同的对象 125 6.3 Hibernate用对象...

    突破程序员基本功的16课.part2

    5.1.1 JVM对字符串的处理 5.1.2 不可变的字符串 5.1.3 字符串比较 5.2 表达式类型的陷阱 5.2.1 表达式类型的自动提升 5.2.2 复合赋值运算符的陷阱 5.3 输入法导致的陷阱 5.4 注释的字符必须合法 5.5 转义...

    JAVA上百实例源码以及开源项目源代码

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    疯狂JAVA讲义

    学生提问:老师,我想学习Java编程,到底是学习Eclipse好呢,还是学习JBuilder好呢? 21 1.9 本章小结 22 本章练习 22 第2章 理解面向对象 23 2.1 面向对象 24 2.1.1 结构化程序设计简介 24 2.1.2 程序的三种...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     6.1 关系数据库按主键区分不同的记录  6.1.1 把主键定义为自动增长标识符类型  6.1.2 从序列(Sequence)中获取自动增长的标识符 6.2 Java语言按内存地址区分不同的对象 6.3 Hibernate用对象标识符(OID)来区分...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     6.1 关系数据库按主键区分不同的记录  6.1.1 把主键定义为自动增长标识符类型  6.1.2 从序列(Sequence)中获取自动增长的标识符 6.2 Java语言按内存地址区分不同的对象 6.3 Hibernate用对象标识符(OID)来区分...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     6.1 关系数据库按主键区分不同的记录  6.1.1 把主键定义为自动增长标识符类型  6.1.2 从序列(Sequence)中获取自动增长的标识符 6.2 Java语言按内存地址区分不同的对象 6.3 Hibernate用对象标识符(OID)来区分...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     6.1 关系数据库按主键区分不同的记录  6.1.1 把主键定义为自动增长标识符类型  6.1.2 从序列(Sequence)中获取自动增长的标识符 6.2 Java语言按内存地址区分不同的对象 6.3 Hibernate用对象标识符(OID)来区分...

    java 面试题 总结

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    JAVA上百实例源码以及开源项目

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

Global site tag (gtag.js) - Google Analytics