jvm概念
jvm是运行java程序的虚拟机。
jvm内存结构
- 1.8之前:
- 1.8之后:
- 内存结构说明:
1)堆:存储所有创建的对象;
2)方法区(元空间):存储类加载后的元数据、静态变量、常量;
3)虚拟机栈:方法运行时内存区域;
4)本地方法栈:存储native方法;
5)程序计数器:存储运行字节码行号; - 是否共享:
堆和方法区(元数据)是线程共享区域,其他事线程私有。
类加载过程
- 加载
在加载阶段,通过全类名来获取描述该类的二进制字节流,也就是.class文件,这个过程被称为加载;
类加载是由类加载器(Class Loader)完成,遵循双亲委派模型流程加载;
jvm中类加载器?
1)启动类加载器BootstrapClassLoader c语言实现,加载rt.jar、resource.jar等;
2)扩展类加载器ExtClassLoader,java实现,加载ext;
3)应用程序类加载器AppClassLoader,java实现;
双亲委派模型?
双亲委派模型工作过程:如果一个类加载器收到了类加载请求,他首先不会自己尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一级的类加载器都是如此,因此所有的类加载请求最终都会传送到最顶层启动类加载器中,只有当上一层类加载器反馈自己无法完成加载时,下一层类加载器才会尝试自己去加载。
双亲委派好处?
1)避免java核心类库被修改;
2)避免重复加载;
3)保证类的唯一性;
怎样实现类加载器?
ClassLoader中有loadClass()、findClass()、defineclass()方法;
loadClass()就是主要进行类加载的方法,默认双亲委派机制实现;
findClass()根据名称或位置加载.class文件;
definclass()把字节码转化为Class,native方法;
实现类加载器,可以重写loadClass方法(破坏双亲委派),不想破坏双亲委派,重新findClass; - 验证
文件是否cafe babe开头,元数据验证等; - 准备
为类的静态变量分配内存,并将其赋默认值
为类变量分配内存并设置类变量初始值,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:
1)只对static修饰的静态变量进行内存分配、赋默认值(如0、0L、null、false等)。
2)对final的静态字面值常量直接赋初值(赋初值不是赋默认值,如果不是字面值静态常量,那么会和静态变量一样赋默认值); - 解析
将常量池中的符号引用替换为直接引用(内存地址)的过程; - 初始化
为类的静态变量赋值;
GC
GC发生在堆内存,GC分为youngGC和fullGC,youngGC发生在年轻代,fullGC发生在老年代会引起stop the world。
哪些对象被回收?
引用计数法和可达性算法,引用计数法在循环依赖情况下无法被回收,所以采用引用计数法;
可达性算法,从GCroot出发,一直沿着引用链向下查找,如果某个对象不能通过GCroot寻找到,那么虚拟机认为这个对象可以被回收。
哪些对象时GCroots?
1)虚拟机栈中引用的对象;
2)本地方法栈引用的对象;
3)方法区中类静态属性引用的对象;
4)方法区中常量引用的对象;
自己理解:只要是被堆外空间引用的对象,都可看作GCroots,不知是否正确?
GC回收算法?
jvm垃圾回收算法:
1)标记清除:产生内存碎片;
2)标记整理:老年代;
3)复制算法:内存x2,新生代;
4)分代垃圾回收算法;
GC垃圾回收器?
新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
整堆收集器: G1
CMS:
jvm调优
常用jvm参数
-Xmx512m -Xms512m -Xss1024k -XX:+PrintGCDetails -XX:+UseParellelGC
oom?
1)java heap space;
2)GC overhead limit exceeded;
3)metaspace;
4)direct buffer memory;
5)unable to create new native thread;
问题排查?
1、oom分析;
2、cpu飙升分析;