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虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...
随机推荐
- emqtt 试用(一)安装和测试
一.安装 http://emqtt.io/docs/v2/getstarted.html http://emqtt.io/docs/v2/advanced.html http://emqtt.io/d ...
- Docker学习笔记 - Docker Compose
一.概念 Docker Compose 用于定义运行使用多个容器的应用,可以一条命令启动应用(多个容器). 使用Docker Compose 的步骤: 定义容器 Dockerfile 定义应用的各个服 ...
- 详解Ajax请求(一)前言——同步请求的原理
我们知道,ajax是一种异步请求的方式,想要了解异步请求,就必须要先从同步请求说起.常见的同步请求的方式是form表单的提交,我们先从一种同步请求的示例说起. 我们希望输入姓名可以从后台得到身份证号. ...
- Windows10+Docker搭建分布式Redis集群(一)
摘要,Docker for Windows 仅支持专业版 目录 第一步:检查系统支持虚拟化 第二步:下载Docker对应版本 第三步:配置镜像加速 第一步:检查系统是否支持虚拟化 Docker前提是需 ...
- 新手创建Vue项目
======================安装vue=============================(参考网址:http://www.bubuko.com/infodetail-21320 ...
- github git 在GitHub上创建项目并将本地项目push到网站上
众所周知,git是与svn类似的版本控制系统,git的去中心化.分布式等的优点,在不久将来用户量大有可能超过svn, 常见的代码托管网站有GitHub,coding.net, gitee.com 码云 ...
- 学习react系列(八)—— mixins迁移
先来介绍一下mixins(混入) 先来看一段代码: const mixin = function(obj, mixins) { const newObj = obj; newObj.prototype ...
- 0316-关于js 注意事项
js:脚本语言,控制网页的行为(特效,表单验证) /* 这是多行注释 *///这是单行注释 js问题及注意事项: JavaScript 对大小写是敏感的 多写注释.提示性文字要说明白 定义变量时最好加 ...
- Spring-cloud(五) 使用Ribbon进行Restful请求
写在前面 本文由markdown格式写成,为本人第一次这么写,排版可能会有点乱,还望各位海涵. 主要写的是使用Ribbon进行Restful请求,测试各个方法的使用,代码冗余较高,比较适合初学者,介意 ...
- [LeetCode] Image Smoother 图片平滑器
Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother t ...