codecamp

JVM

笔者能力有限,总结有误的地方,请读者协作更正。

1.类的加载机制

关注点: 什么是类的加载 类的生命周期 类加载器 双亲委派模型

1)谈一谈类的实例化顺序,比如:父类静态数据,构造函数,字段等的执行顺序? 先静态-->先父后子-->非静态代码块-->构造函数

2)java代码的执行编译过程 ? 主要就是两部:java源文件由编译器编译成字节码文件,字节码文件由虚拟机解释执行。

具体来说,源码需要经过词法分析器组件,语法分析器组件,语义分析器组件,最后经过代码生成器组件编译成字节码文件。

3)java类的生命周期?

一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况。

4)类加载器?

类加载器是java语言强大的特征之一, 默认情况下有三种类加载器(引导类加载器,扩展类加载器,应用类加载器),我们也可以自定义类加载器。 应用程序的每一个类都由ClassLoader加载,java类是被动态的加载到内存,java的一大特点,也称为运行时绑定。

5)什么是类加载器的双亲委派模型?

就是类加载器之间的的层次关系,该模型要求除了顶层的启动类加载器之外,其余的类加载器都要有父类加载器,而且这种关系一般通过组合关系来实现,而不是通过继承。

某一个类加载器在接到加载类的请求时候,首先会将任务委托给父类加载,依次递归,如果父类加载器可以完成类加载任务,则成功返回;如果父类加载器无法完成加载任务,将抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载,依次类推。

好处:

防止内存中出现多份同样的字节码。 如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证,将会给虚拟机的安全带来隐患。

2.JVM内存结构

关注点: 内存结构 对象分配规则

1)JVM的内存分配?

Java虚拟机的运行时数据区包括:Java堆、Java虚拟机栈、方法区、PC寄存器、本地方法栈,还有常量池。它们被分为两大类-------线程共享、私有数据区。

2)虚拟机内存分配的各个区域作用?

堆:

new处理的对象都存放在堆中,堆的大小可以通过-Xmx和-Xms来控制; 堆被分为新生代、旧生代、持久代新创建的对象都用新生代内存分配,旧生代用于存放新生代中多次经过垃圾回收仍然存活的对象;

栈:

每个线程执行每个方法时候都会在栈中申请一个栈帧,用于存放此次方法调用过程中临时的变量、参数、中间结果等;

本地方法栈:

用于支持native方法执行,存储每个native方法调用的状态

方法区:

持久代实现方法区,主要用来存放已经加载的类的信息,方法,常量等;可以通过XX:PermSize和-XX:MaxPermSize来指定持久带初始化值和最大值。

3.GC算法 垃圾回收

关注点: 对象存活判断 GC算法 垃圾回收器

1)垃圾回收采用什么算法实现?按照基本策略分为:

引用计数器(Reference Counting): 比较旧的一个算法,原理是此对象有一个引用;增加一个计数,增加一个引用;删除一个引用,减少一个计数。 垃圾回收时,只收集计数为0的对象。 存在最致命的问题是,无法处理循环引用的问题。

标记-清除(Mark-Sweep): 此算法分为两个阶段,第一个阶段从引用根节点开始标记被引用的对象; 第二个阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

复制(Copying): 此算法把内存空间划分为相等的区域,每次只使用其中一个区域,垃圾回收时候,遍历当前的区域,把正在使用中的对象复制到另一个区域。 算法每次只处理正在使用的对象,因为复制成本小,同时复制过去之后还能进行相应的内存调整,不会出现碎片问题。 缺点就是,需要两倍的内存空间。

标记-整理(Mark-Compact): 此算法集合了“标记-清除”和“复制”两个算法的优点分为两个阶段,第一阶段从根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把清除未标记的对象并且存活的对象“压缩”到堆的其中一块,按照顺序排放。 此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。

2)Java对新生代和旧生代采取了不同的垃圾回收机制

新生代的GC: 新生代通常存活时间较短,居于Coping算法来进行回收; 采用空指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间位置,当有新的对象要分配内存时候,用于检查空间是否足够,不够就触发GC; 在执行机制上提供了串行GC,并行回收GC,和并行GC;

旧生代GC: 旧生代GC对象存活的时间比较长,比较稳定;

采用标记(Mark)算法来进行回收,就是扫描出存活的对象,回收位被标记的对象,回收后对对腾出的空间进行合并。 在执行机制上JVM提供了串行GC,并行GC和并发GC;

4.GC分析 命令调优

关注点: GC日志分析 调优命令 调优工具

调优主要的目的是减少GC的频率和Full GC的次数,过多的GC和Full GC是会占用很多的系统资源(主要是CPU),影响系统的吞吐量。

调优手段:主要是通过控制堆内存的各个部分的比例和GC策略来实现,JVM提供两种较为简单的GC策略的设置方式;

1)吞吐量优先     JVM以吞吐量为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,来达到吞吐量指标。这个值可由-XX:GCTimeRatio=n来设置

2)暂停时间优先     JVM以暂停时间为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,尽量保证每次GC造成的应用停止时间都在指定的数值范围内完成。这个值可由-XX:MaxGCPauseRatio=n来设置

想了解更多请阅读
https://www.zybuluo.com/Yano/note/321063

反射
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

第2章 数据库

SQL

第4章 hadoop

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }