浅入理解JVM虚拟机


1. 类加载过程

验证 —— 准备 —— 解析 —— 初始化

验证阶段: 判断.class文件符合规范标准

准备阶段:给类以及静态变量分配内存并给初始值 “0”

解析阶段: 维护哥哥字段,方法类的内存指针或偏移量

初始化阶段:  变量赋值(真实的值),执行代码

什么时候一个类会进行初始化阶段?

1.new一个实例化对象时

2.包含main方法的主类

3.需要初始化子类时,必须先初始化父类

2. Tomcat如何实现热部署?

类加载器与双亲委派机制

启动类加载器 —— 扩展类加载器 —— 应用类加载器 —— 自定义类加载器

双亲委派机制也就是拿到一个类,先交给他的父类加载器加载,一层一层传递,如果都加载不了再回到自己的加载器加载,

这样就保证了每个类都会尽可能的在最上层加载器加载,且只会加载一次。保证了沙箱安全

Tomcat的实现方式

第一种,在WEB-INFO/class 目录下的文件,使用WebApp类加载器

启用一个线程来检测class文件的modify时间是否发生变化,如果发生变化就时1开关reloadable = true,使整个容器重启,全部重新加载

第二种,jsp类文件使用Jsp类加载器加载,Jsp类加载器属于一次性的

当jsp文件每次被修改时,都会使用一个新的Jsp类加载器加载。每此都会有新的jsp加载到jvm,并丢弃上一个

3. 垃圾回收器与垃圾回收算法

1.复制算法,用于新生代,Eden区与s1区中存活对象复制到s2区,剩下对象干掉

优点:不会产生内存碎片  缺点: 始终浪费一块空间

2.标记清除算法,用于老年代,先标记出哪些是垃圾,再统一清理

优点:节省空间     缺点:容易产生内存碎片

3.标记整理算法,用于老年代,就是在标记清除的基础上加一次整理,把内存碎片干掉

缺点:耗时

ParNew垃圾回收器,用于新生代,支持多线程,STW

CMS垃圾回收器,用于老年代,四个阶段  初始标记(标记GCRoot直接引用对象) —— 并发标记(GCRoot间接引用对象) —— 再次标记(补充并发标记中创建的对象) —— 并发清除 

 其中初始标记和再次标记是STW的,也占用的时间比较短

CMS采用标记清除,可配置JVM参数,多少次标记清除后一次标记整理

4. 关于GCRoot

用作可达性分析的根,一般是类静态变量和栈中的局部变量的对象

finalize()方法,

GC前会调用该对象的finallize()方法,试图抢救一下。所以可以在该方法中将当前对象挂上GCRoot链路,避免被回收

finalize 方法只会被执行一次,如果第一次执行 finalize 方法此对象变成了可达确实不会回收,但如果对象再次被 GC,则会忽略 finalize 方法,对象会被回收!

5. 关于方法区

方法区属于概念,jdk1.8之前是永久代实现(与堆内存连续的),之后是元空间实现(在JVM外的本地内存)

方法区存的是类的模板,动态生成的类,静态变量,常量池(注意1.8以后常量池物理上存在于堆内存,但是逻辑上还是属于方法区的,咱也不懂)

方法区发生回收需要满足的条件

1.该类的所有实例对象都已经被JVM回收

2.加载该类的类加载器被回收

3.该类的Class对象没有任何引用

(个人感觉这些条件如此苛刻,因此方法区溢出导致的FullGC大概率并不会导致方法去回收,从而导致无限的FullGC)

对象进入老年代的几种情况(如何避免进入老年代)

发生FullGC的几种情况

Java服务CPU打满的几种情况

GC调优的思路

GC调优工具

JVM调优案例分析

相关