JVM常见问题(二)
6. GC收集器有哪些?它们的特点是?
1.Serial收集器(串行收集器)
2.ParNew收集器(parallel new 收集器,新生代并行收集器)
3.Parallel Scavenge收集器
4.Serial Old收集器
5.Parallel Old收集器
6.CMS收集器(Concurrent Mark Sweep,并发标记清除收集器)
- 初始标记,需要stop the world,标记GC Root能关联到的对象,速度快
- 并发标记,对GC Root执行可达性算法
- 重新标记,需要stop the world,修复并发标记时因用户线程运行而产生的标记变化,所需时间比初始标记长,但远比并发标记短
- 并发清理
- 其对于CPU资源很敏感。在并发阶段,虽然CMS收集器不会暂停用户线程,但是会因为占用了一部分CPU资源而导致应用程序变慢,总吞吐量降低。其默认启动的回收线程数是(cpu数量+3)/4,当cpu数较少的时候,会分掉大部分的cpu去执行收集器线程
- 无法处理浮动垃圾,浮动垃圾即在并发清除阶段因为是并发执行,还会产生垃圾,这一部分垃圾即为浮动垃圾,要等下次收集
- CMS收集器使用的是标记清除算法,GC后会产生碎片
7.G1收集器(Garbage First收集器)
- 使用标记整理算法,确保GC后不会产生内存碎片
- 可以精确控制停顿,允许指定消耗在垃圾回收上的时间
7. Minor GC与Full GC分别在什么时候发生?
8. 类加载的五个过程:加载、验证、准备、解析、初始化
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的生命周期包括了:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称链接。
1.加载
- 通过一个类的权限定名来获取定义此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在java堆中生成一个代表这个类的java.lang.Class对象,作为方法去这些数据的访问入口
2.验证
- 文件格式验证:验证class文件格式规范
- 元数据验证:这个阶段是对字节码描述的信息进行语义分析,以保证起描述的信息符合java语言规范要求
- 字节码验证:进行数据流和控制流分析,这个阶段对类的方法体进行校验分析,这个阶段的任务是保证被校验类的方法在运行时不会做出危害虚拟机安全的行为
- 符号引用验证:符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用类中的类,字段和方法的访问性(private、protected、public、default)是否可被当前类访问
3.准备
4.解析
- 类或接口的解析
- 字段解析
- 类方法解析
- 接口方法解析
5.初始化
9. 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader
- 启动类加载器(Bootstrap ClassLoader):是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作
- 标准扩展类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器
- 应用程序类加载器:由sun.misc.Launcher$AppClassLoader实现,负责加载用户类路径classpath上所指定的类库,是类加载器ClassLoader中的getSystemClassLoader()方法的返回值,开发者可以直接使用应用程序类加载器,如果程序中没有自定义过类加载器,该加载器就是程序中默认的类加载器
从JDK1.2开始,JVM规范推荐开发者使用双亲委派模式(ParentsDelegation Model)进行类加载,其加载过程如下:
- 如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器去完成
- 每一层的类加载器都把类加载请求委派给父类加载器,直到所有的类加载请求都传递给顶层的启动类加载器
- 如果顶层的启动类加载器无法完成加载请求,则子类加载器会尝试去加载,如果连最初发起类加载请求的类加载器也无法完成加载请求时,将会抛出ClassNotFoundException,而不再调用其子类加载器去进行类加载
10. 分派:静态分派与动态分派
- 静态类型:变量声明时的类型
- 实际类型:变量实例化时采用的类型
- class Car {}
- class Bus extends Car {}
- public class Main {
- public static void main(String[] args) throws Exception {
- // Car 为静态类型,Bus 为实际类型
- Car car = new Bus();
- }
- }
静态分派
- class Car {}
- class Bus extends Car {}
- class Jeep extends Car {}
- public class Main {
- public static void main(String[] args) throws Exception {
- // Car 为静态类型,Car 为实际类型
- Car car1 = new Car();
- // Car 为静态类型,Bus 为实际类型
- Car car2 = new Bus();
- // Car 为静态类型,Jeep 为实际类型
- Car car3 = new Jeep();
- showCar(car1);
- showCar(car2);
- showCar(car3);
- }
- private static void showCar(Car car) {
- System.out.println("I have a Car !");
- }
- private static void showCar(Bus bus) {
- System.out.println("I have a Bus !");
- }
- private static void showCar(Jeep jeep) {
- System.out.println("I have a Jeep !");
- }
- }
代码输出如下:
从上面的例子我们可以看出重载调用的具体方法版本是由静态类型来决定的。
动态分派
- class Car {
- public void showCar() {
- System.out.println("I have a Car !");
- }
- }
- class Bus extends Car {
- public void showCar() {
- System.out.println("I have a Bus !");
- }
- }
- class Jeep extends Car {
- public void showCar() {
- System.out.println("I have a Jeep !");
- }
- }
- public class Main {
- public static void main(String[] args) throws Exception {
- // Car 为静态类型,Car 为实际类型
- Car car1 = new Car();
- // Car 为静态类型,Bus 为实际类型
- Car car2 = new Bus();
- // Car 为静态类型,Jeep 为实际类型
- Car car3 = new Jeep();
- car1.showCar();
- car2.showCar();
- car3.showCar();
- }
- }
运行结果如下:
可以看出来重写是一个根据实际类型决定方法版本的动态分派过程。
JVM常见问题(二)的更多相关文章
- Java虚拟机详解----JVM常见问题总结
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- JVM(二)Java虚拟机组成详解
导读:详细而深入的总结,是对知识"豁然开朗"之后的"刻骨铭心",想忘记都难. Java虚拟机(Java Virtual Machine)下文简称jvm,上一篇我 ...
- JVM总括二-垃圾回收:GC Roots、回收算法、回收器
JVM总括二-垃圾回收:GC Roots.回收算法.回收器 目录:JVM总括:目录 一.判断对象是否存活 为了判断对象是否存活引入GC Roots,如果一个对象与GC Roots没有直接或间接的引用关 ...
- JVM(十二):方法调用
JVM(十二):方法调用 在 JVM(七):JVM内存结构 中,我们说到了方法执行在何种内存结构上执行:Java 方法活动在虚拟机栈中的栈帧上,栈帧的具体结构在内存结构中已经详细讲解过了,下面就让我们 ...
- 深入JVM(二)JVM概述
深入JVM(一)JVM指令手册 深入JVM(二)JVM概述 一.JVM的原理 Java虚拟机是Java平台的基石,解决了硬件和操作系统的相互独立性.不同平台(Windows,Linux和MacOS)的 ...
- JVM常见问题分析
JVM常见问题分析 启动,并且去查看日志 ./startup.sh && tail -f ../logs/catalina.out 常见有有以下几个问题: 1.java.lang.Ou ...
- JVM系列二:GC策略&内存申请、对象衰老
JVM里的GC(Garbage Collection)的算法有很多种,如标记清除收集器,压缩收集器,分代收集器等等,详见HotSpot VM GC 的种类 现在比较常用的是分代收集(generatio ...
- JVM的生命周期——JVM之二
一.首先分析两个概念 JVM实例和JVM执行引擎实例 (1)JVM实例对应了一个独立运行的java程序——进程级别 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程 ...
- jvm系列 (二) ---垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...
随机推荐
- 从一个事件绑定说起 - DOM
事件绑定的方式 给 DOM 元素绑定事件分为两大类:在 html 中直接绑定 和 在 JavaScript 中绑定. Bind in HTML 在 HTML 中绑定事件叫做内联绑定事件,HTML 的元 ...
- python isinstance 函数
isinstance是Python中的一个内建函数 语法: isinstance(object, classinfo) 如果参数object是classinfo的实例,或者object是class ...
- Python入门之ATM+购物车代码版思维导图
该项目结合了ATM模版和购物车需求,整个思维导图用Python代码实现,使用思维导图可以清晰明了的看清整个框架: 过程中,用到了Python的知识有Python常用模块,Python常用内置包,log ...
- 解决Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/Student_recruit]]
查看web.xml文件的书写,特别注意路径与命名一致
- python模块之PIL模块
PIL简介 什么是PIL PIL:是Python Image Library的缩写,图像处理的模块.主要的类包括Image,ImageFont,ImageDraw,ImageFilter PIL的导入 ...
- scrapy选择器主要用法
# 命令行输入:scrapy shell +链接,会自动请求url,得到的相应默认为response,开启命令行交互模式 scrapy shell http://doc.scrapy.org/en/l ...
- CountDownLatch与thread-join()的区别
今天学习CountDownLatch这个类,作用感觉和join很像,然后就百度了一下,看了他们之间的区别.所以在此记录一下. 首先来看一下join,在当前线程中,如果调用某个thread的join方法 ...
- glut 深度测试无不起作用问题解决
OpenGL中使用glEnable(GL_DEPTH_TEST)后深度测试没有起作用,发现深度缓冲没有创建.glut库在兼容模式(GL_COMPATIBILITY_PROFILE)下displaymo ...
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)
题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了 代码如下: #include<cstdio> #include<vector> #in ...
- JavaScript数据结构与算法(五) 数组基础算法