jvm理解


1、程序计数器
每个线程都有自己的计数器,用来指示程序将要运行到哪一行。
2、虚拟机栈
  虚拟机栈描述的是java方法执行的内存模型,为线程私有。
  每个方法执行时都会创建一个栈帧,用于存储 局部变量,操作数栈,动态链接,方法出口等。
  每个方法执行从开始到完成对应为栈帧从入栈道出栈的过程。
3、本地方法栈
  本地方法栈与虚拟机栈类型,不同的为 虚拟机栈执行的是 java方法,本地方法栈执行的是 native方法。
4、堆
  堆是线程共享,主要存放 对象实例 和数组。
新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。
新生代几乎是所有 Java 对象出生的地方,即 Java 对象申请的内存以及存放都是在这个地方。Java 中的大部分对象通常不需长久存活,具有朝生夕灭的性质。
当一个对象被判定为 "死亡" 的时候,GC 就有责任来回收掉这部分对象的内存空间。新生代是 GC 收集垃圾的频繁区域。
当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。
但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。

Java堆可以分为新生代和老年代两个区,其中新生代又可以分为一个Eden区和两个Survivor区,两个Survivor区分别被命名为From和To以示区分,新生代和老年代的比例为1:2,它们共同组成堆的内存区,所以新生代占堆的1/3,老年代占2/3,但这个比例可以修改,下面分别来介绍一下新生代和老年代。
1、【新生代】
新生代分为三个区域,一个Eden区和两个Survivor区,它们之间的比例为(8:1:1),这个比例也是可以修改的。通常情况下,对象主要分配在新生代的Eden区上,少数情况下也可能会直接分配在老年代中。Java虚拟机每次使用新生代中的Eden和其中一块Survivor(From),在经过一次Minor GC后,将Eden和Survivor中还存活的对象一次性地复制到另一块Survivor空间上(这里使用的复制算法进行GC),最后清理掉Eden和刚才用过的Survivor(From)空间。将此时在Survivor空间存活下来的对象的年龄设置为1,以后这些对象每在Survivor区熬过一次GC,它们的年龄就加1,当对象年龄达到某个年龄(默认值为15)时,就会把它们移到老年代中。
在新生代中进行GC时,有可能遇到另外一块Survivor空间没有足够空间存放上一次新生代收集下来的存活对象,这些对象将直接通过分配担保机制进入老年代;
总结:
1、Minor GC是发生在新生代中的垃圾收集,采用的复制算法--将内存分为2个区域,将存活的对象移到另一个内存区域,清理原来的内存区域;
2、新生代中每次使用的空间不超过90%,主要用来存放新生的对象;
3、Minor GC每次收集后Eden区和一块Survivor区都被清空;

2、【老年代】
老年代里面存放都是生命周期长的对象,对于一些较大的对象(即需要分配一块较大的连续内存空间),是直接存入老年代的,还有很多从新生代的Survivor区域中熬过来的对象。
老年代中使用的是Full GC,Full GC所采用的是标记-清除算法。老年代中的Full GC不像Minor GC操作那么频繁,并且进行一次Full GC所需要的时间要比Minor GC的时间长。
标记/清除算法 就应运而生了,它的做法是 当堆中的有效内存空间(available memory)被耗尽的时候,就会停止整个程序(也被成为stop the world),然后进行两项工作,第一项则是标记,第二项则是清除
(1)标记:标记的过程其实就是,遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。
(2)清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。
    其实这两个步骤并不是特别复杂,也很容易理解。LZ用通俗的话解释一下标记/清除算法, 就是当程序运行期间,若可以使用的内存被耗尽的时候,GC线程就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没被标记的对象全部清除掉 ,接下来便让程序恢复运行。
若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收
总结:
1、老年代中使用Full GC,采用的标记-清除算法
标记-清除算法采用从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如上图所示。标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。


5、方法区

方法区存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。

JVM用永久代(PermanetGeneration)来存放方法区,(在JDK的HotSpot虚拟机中,可以认为方法区就是永久代,但是在其他类型的虚拟机中,没有永久代的概念 )。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值