深入理解JVM内存模型
1、程序计数器在虚拟机的概念模型里字节码解释器工作时就是通过改变
这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、
Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现
的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行
一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要
有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内
存区域为“线程私有”的内存。
线程恢复等基础功能都需要依赖这个计数器来完成。
2、线程栈VM栈的默认大小是1M。用于在调用函数时持有局部变量并维护状态的内存区域
-Xss 128k:设置每个线程的堆栈大小。不能无限生成,经验值在3000~5000左右
线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时
时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会
出现内存溢出的错误.
异常 :Fatal: Stack size too small
异常的引起一般是线程数目太多
3、本地方法栈
即为一些Native方法分配的stack
Native方法,java调用C程序
在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
4、栈每个线程的栈都是该线程私有的,堆则是所有线程共享的,这里说的堆,主要指程序能控制的,包括
新生代:The New Generational Heap,默认4M,此区域一般为JVM内存的1/15大小。此代分为Eden space区,Survivo space区可以看成emptySurvivo区,Survivor区,
每次算法开始都得停止当前所有的线程,然后把Survivor区的所有活跃的对象复制到emptySurvivo区,然后对Survivor区空间进行清除变成emptySurvivo,以前的emptySurvivo成为了Survivor区。(互换)
当new 一个对象时,首先是在Eden space区,当Eden space区满时,Survivor space区进行垃圾回收(此处复制算法),当对象在Survivo space区经过几次回收Tenured Generation
老年代:此处储存年老代的对象,此处的垃圾回收采用The Mark and Sweep 算法
5、垃圾回收算法: 标记-清除算法从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片!
复制算法:根集合扫描,并将存活对象复制到一块新的,没有使用过的空间中,这种算法当控件存活的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间用于进行对象的移动。也就是我们前面提到的
s0 s1等空间。(Survivor 0和Survivor 1(这个估计是old Generation区?))
标记整理算法:采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。
对于新生代内存的回收(minor GC)主要采用复制算法
分代收集分代收集是利用程序有大量临时对象的特点,对象每被引用一次,代数就增加,代数小的小型对象会被回收整理,大对象只会代数增加,不会被整理。
引用计数:当引用连接到对象时,对象计数加1,当引用离开作用域或被置为null时减1。遍历对象列表,计数为0就释放
6、垃圾回收器:因为GC主要就是对堆的回收,当然还有常量池和永久代
a、单线程程收集器serial collector:Stop The World垃圾回收器
Client下默认方式串行回收方式适合低端机器,是Client模式下的默认收集器,对CPU和内存的消耗不高,适合用户交互比较少,后台任务较多的系统。
b、并行收集器parallel collector
多线程版本的Serial收集器他是多CPU模式下的首选回收器
c、CMS又称响应时间优先(最短回收停顿)的回收器,使用并发模式回收垃圾,使用标记-清除算法,CMS对CPU是非常敏感的,它的回收线程数=(CPU+3)/4,因此当CPU是2核的实惠,回收线程将占用的CPU资源的50%,而当CPU核心数为4时仅占用25%
分四步骤:在初始标记的时候,需要中断所有用户线程,在并发标记阶段,用户线程和标记线程并发执行,而在这个过程中,随着内存引用关系的变化,可能会发生原来标记的对象被释放,进而引发新的垃圾,因此可能会产生一系列的浮动垃圾,不能被回收。
CMS在旧生代内存到达全部容量的68%就触发了CMS的回收!
d、G1收集器
商用高性能垃圾回收器,通过重新划分内存区域,整合优化CMS,
7、当然还一种程序调用system.gc()
调用System.gc()也仅仅是一个请求。JVM接受这个消息后,并不是立即做垃圾回收,而只是对几个垃圾回收算法做了加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。
8、垃圾回收的触发
new generation来说,当eden区的对象空大于Survivor0(假设为from)的free空间时,会发生minor gc,即对整个Survivor0区,Survivor1区进行一个复制算法垃圾回收,并且部分对象转到Old Generation
当new generation满了(即eden区+Survivor0区大于Old Generation的free空间时),将发生major gc,即对New Generation和Old Generation两代都进行垃圾回收。
所以得出,如果JVM的设置内存过大,发生GC的回收频率将越小,但是回收的时间越长(特别对new generation进行复制算法的复制时是需要停止当前所有线程的),所以并不是说JVM的内存设置的越大越好,得根据实际情况进行优化。
异常:异常 java.lang.OutOfMemoryError: Java heap space
一般是由于垃圾回收后,old generation里空间也不够用了。
9、堆内存的分配
-server时最大堆内存是物理内存的1/4,但小于1G
client 小一倍
参数:-Xms128m
表示JVM Heap(堆内存)最小尺寸128MB,初始分配
-Xmx512m
表示JVM Heap(堆内存)最大允许的尺寸256MB,按需分配
new Generation与Old Generation的比例,默认为1:2,即为2
-XX:NewRatio= 参数可以设置(也可以-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值)
Eden与Survivor的比例,默认为32
-XX:SurvivorRation=参数可以设置
当对象默认经过1次New Generation 就转入Old Generation(这个不同文章上不同,待我确定)
10、方法区、永久栈Perm
其实也可与看成堆内存的一部分,看成永久代(Perm Space),但GC也会回收,但很少回收,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,比如一个int x,在不同的环境中是不同的,此信息就存在方法区
XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 设置垃圾不回收
-server选项下默认MaxPermSize为64m
-client选项下默认MaxPermSize为32m
11、常量池
编译期已可知的常量,这部分内容将在类加载后进入方法区(永久代)存放
GC的作用主要是用来卸载类和回收常量池,当然有部分方法区,即使永久代(Perm Space)也会一定的回收运行期间也可将新内容放入常量池(最典型的String.intern()方法)
12、所有线程共享主内存
每个线程有自己的工作内存。。每个线程都有自己的执行空间(即工作内存),线程执行的时候用到某变量,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作:读取,修改,赋值等,这些均在工作内存完成,操作完成后再将变量写回主内存;
多个线程同时读写某个内存数据时,就会产生多线程并发问题,涉及到三个特 性:原子性,有序性,可见性。
深入理解JVM内存模型的更多相关文章
- 如何从编程的本质理解JVM内存模型
如何从编程的本质理解JVM内存模型 一般聊JVM内存模型都是把图截出来,然后对着图,解释上面堆.栈之类的概念.这篇将分享下,如何从编程的本质上理解,JVM内存模型是什么样子,为什么是这个样子,不再死记 ...
- java 深入理解jvm内存模型 jvm学习笔记
jvm内存模型 这是java堆和方法区内存模型 参考:https://www.cnblogs.com/honey01/p/9475726.html Java 中的堆也是 GC 收集垃圾的主要区域.GC ...
- 深入理解JVM(一)——JVM内存模型
JVM内存模型 Java虚拟机(Java Virtual Machine=JVM)的内存空间分为五个部分,分别是: 1. 程序计数器 2. Java虚拟机栈 3. 本地方法栈 4. 堆 5. 方法区. ...
- 深入理解java虚拟机学习笔记(一)JVM内存模型
上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...
- 深入理解JVM - JVM内存模型
各版本的差异 JDK1.6 在JDK1.6 的时候运行时常量池在方法区中 JDK1.7 在JDK1.7 的时候运行时常量池在堆中 JDK1.8 在JDK1.8 的时候,JVM内存模型直接将方法区移到了 ...
- JVM初探 -JVM内存模型
JVM初探 -JVM内存模型 标签 : JVM JVM是每个Java开发每天都会接触到的东西, 其相关知识也应该是每个人都要深入了解的. 但接触了很多人发现: 或了解片面或知识体系陈旧. 因此最近抽时 ...
- jvm内存模型和内存分配
1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的. (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和 ...
- JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
(转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...
- JVM内存模型以及垃圾收集策略解析
http://xmuzyq.iteye.com/blog/599750 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程. ...
随机推荐
- [转]SQLServer2008日志文件无法收缩处理方法
问题描述 发现有的数据库日志文件太大,无论如何收缩执行几次SQL语句都不行.事务日志达30+G,而且使用常规的截断.收缩方法均无法减小日志物理文件的尺寸,经过一番寻找,终于找到了解决方法. 查 ...
- 关于CGContextSetBlendMode: invalid context 0x0的错误
在ios 7的模拟器中,选择一个输入框准备输入时,会触发这个错误,以下是出错详细日志: <Error>: CGContextSetBlendMode: invalid context 0x ...
- linux iostat 性能指标说明
Linux系统中的 iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视. 它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况. ...
- 更改RAC日志组
alter database add logfile thread 1 group 5 ('+DATA/idb/onlinelog/group5.log') size 256m;alter datab ...
- OFBIZ:启动之ContainerLoader
ContainerLoader类实现StartupLoader接口,目的是装入各种Container容器. /** * An OFBiz container. A container can be t ...
- 使用BeanUtils工具类操作Java bean
1.类的属性: 1).在Java EE中,类的属性通过setter和getter定义:类中的setter(getter)方法去除set(get)后剩余的部分就是类的属性 2).而之前叫的类的属性,即成 ...
- Karma 5:集成 Karma 和 Angular2
集成 Karma 和 Angular2 我们需要做很多工作,由于需要使用 TypeScript 进行开发,首先需要正确配置 Typescript ,然后正确配置对 Angular2 的引用.还要创建 ...
- 【C#基础】System.Reflection (反射)
在使用.NET创建的程序或组件时,元数据(metadata)和代码(code)都存储于"自成一体"的单元中,这个单元称为装配件.我们可以在程序运行期间访问这些信息.在System. ...
- markdown 的基本操作
文档 http://mux.alimama.com/posts/620?spm=0.0.0.0.4VVnvp http://www.jianshu.com/p/1e402922ee32/ MdChar ...
- phpunit.xml
<phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name=&quo ...