JVM知识点笔记(一)--- 内存模型部分知识点

一、内存划分图,网上的图有好几种和书上的 也都有些不同,但是关键部分都一样,所以随便找一个图贴上(图片来源:https://segmentfault.com/a/1190000008134012)。



二、各个区域介绍(堆,方法区,和本地方法栈重点了解和记忆)

1、堆内存:
   1.1   java堆是jvm内存管理中最大的一块,线程共享。在jvm启动的时候创建。此区域唯一目的就是存放对象实例

    java堆细分为新生代和老年代,新生代又分为Eden区、From Survivor(S0)区、To Survivor(S1)区,新生代中垃圾回收 算法默认为复制算法.

  1.2   复制算法是先将内存分为2个部分,一部分用来放入对象,而另一部分暂时不用,当使用的一部分内存要进行垃圾回收的时候会将不需要回收的对象复制保存在另一个空间中,然后再对使用过的那部分区域进行垃圾回收,这样虽然效率很高,但是很浪费空间,所以一般将新生代分为Eden空间和两个Survivor空间,具体回收过程是将Eden区域和From Survivor区域作为对象的存储空间,当要进行垃圾回收的时候先将这两个区域中不需要回收的对象复制保存在To Survivor区域中,然后再进行垃圾回收。

 1.3    当一个对象在Eden区域和From Survivor区域中存储的时候发现内存不足,这时会进行内存分配担保,就是将此对象直接   存入在老年代中; 当一个特别大的对象创建的时候(通过 -XX:PretenureSizeThreshold设置大小),也会直接进入老年代  ;

    使用PretenureSizeThreshold可以进行指定进入老年代的对象大小,但是要注意TLAB区域会优先分配空间,只有TLAB也不够之后才会进如老年代。TLAB本身占用eEden区空间,在开启TLAB的情况下,虚拟机会为每个Java线程分配一块TLAB空间。参数-XX:+UseTLAB开启TLAB,默认是开启的。TLAB空间的内存非常小,缺省情况下仅占有整个Eden空间的1%,当然可以通过选项-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比大小

    当在新生代中经过15(默认)次GC后依然存活的对象,也会进入老年代;

    新生代的GC叫做 Minor GC (深入理解jvm虚拟机一书中的定义);

    大部分对象都会在新生代的GC中被回收,且新生代的GC执行速度很快,因为进行GC的时候会造成系统停顿,而老年待进行GC时,停顿时间较长,所以应通过参数优化尽量减少老年代的Full GC频率。


1.4  老年代进行垃圾回收时叫 Full FC ,采用的GC算法为标记-清除算法或者标记-整理算法。标记-清除算法为:首先标记出要进行GC的对象,标记完成后再进行GC。这种算法效率不高,并且会产生很多内存碎片。标记-整理算法:同样是先对要进行GC的对象进行标记,但是不同的是在标记完成后不是立刻执行GC,而是先将不需要GC的对象移动到一端,然后在边界外再对要回收的对象进行GC。


   
 
2、方法区
    方法区又被称为永久区,线程共享,是用来存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区为堆的一个逻辑部分,但是在JDK1.7的HotSpot中已经将方法区中的字符串常量池移出,部分资料显示JDK1.8已经去除了方法区(不确定)。不过已经可以猜测此区域将会被本地内存逐步取代。
    这个区域很少进行垃圾回收,回收目标主要是针对常量池的回收和对类型的卸载。
 
3、JVM栈
    JVM栈是线程私有的,它的生命周期与线程相同。JVM栈描述的是java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
    局部变量表中存放了编译期可知的各种基本数据类型、对象的引用类型。局部变量表中需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
 
4、本地方法栈
    本地方法栈和JVM栈非常相似,它们之间的区别不过是jvm栈是为执行java方法服务,而本地方法栈是为jvm使用到对的本地方法服务。HotSpot虚拟机中直接把本地方法栈和JVM栈合二为一了。
 
5、程序计数器
    程序计数器是一块较小的内存空间,线程私有。它可以看作是当前线程所执行的字节码的行号指示器。在jvm的概念模型里,字节码解释器工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
    如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的jvm字节码指令的地址;如果正在执行的是本地方法,这个计数器值则为空。
 
总结:

    在jvm划分的内存区域中JVM栈和本地方法栈可能会抛出StackOverflowError异常和OutOfMemoryError异常。java堆和方法区可能会抛出OutOfMemoryError异常。程序计数器中没有地方规定会抛出这两个异常。


三、垃圾回收算法:

 CMS算法和G1算法是目前可以支持并行处理的算法,理论上可以减少其它算法产生的停顿问题,重点记忆一下。这些就不写了,百度一下很多,就不记录了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值