真正读懂jvm

 

 

一、java 文件在jvm 中的执行过程

一、装载
1.将java文件编译成字节码文件,字节码文件是java 虚拟机可以识别的文件
2.将java 字节码文件通过流的方式装载到内存,也就是按照虚拟机所需的格式存储在方法区中,同时在java 堆中生成一份java.lang.Class 对象,这个对象是作为类的访问入口
二、验证
1.验证二进制字节流中的信息符合jvm 存储规范,是否按照0xCAFEBABE开头,主次版本号是否在当前虚拟机的所在范围
2.元数据验证,保证其描述的信息符合java 语言规范
三、准备
1.正式为类的静态变量分配内存和分配初值,这个内存分配是在方法区中分配的
2.在准备阶段会给常量赋默认值,比如0,false,null 等,但是如果是final 常量,则准备阶段直接赋于最终的值(代码中指定的值)
四、解析
1.将符号引用转为直接引用,也就是将虚拟机常量池中的符号引用(int a=)转为直接引用(变量的内存地址),符号引用只是用文本的方式表示引用关系,而符号引用是jvm可以直接使用的形式,主要表现为直接指针
五、初始化
1.给申明的类变量指定初始值,如a=3
2.给类的静态代码块变量指定初始值
3.如果该类的父类没有初始化,则先初始化该类的父类
4.类的初始化时机包括:new ;访问某个类的静态变量或赋值;反射(Class.forName);被标明为启动类的类
六、生命周期结束
1.生命周期结束的集中情况:执行System.exit();程序正常执行结束;程序遇到异常或错误导致执行结束;操作系统错误导致结束

 二、jvm 内存模型(运行时数据区)

 

 

 

1.方法区:用户存储虚拟机加载的类信息、常量、静态变量,是各个线程共享的区域。

2.堆:用来存储对象及数组实例,是jvm 管理内存的最大一块区域,分为老年代和年轻代,堆也是各个线程共享的区域。

3.java 虚拟机栈:java 方法执行的内存区域,用来存储局部变量表,操作数栈、方法出口,虚拟机栈是线程私有的,每个线程调用方法都会产生一个栈

4.本地方法栈:和虚拟机栈类似,虚拟机栈是为虚拟机执行的java方法服务,而本地方法栈是为虚拟机执行的native 方法(c++写的)服务;

5.程序技术器:用来记录当前线程执行的字节码的行号指令器,分支、循环、异常处理、线程恢复都要依赖于程序计数器,通过程序计数器来选取下一条程序执行的字节码指令,程序计数器也是线程私有的。

 

三、java 虚拟机栈执行过程

 1.当某个线程在执行时,先开辟一块栈空间,在栈空间中每调用一次方法就会生成一个栈帧,每个栈帧,也就是方法遵循先进后出

2.栈帧中包含:局部变量表、操作数栈、动态连接、方法出口

3.一段代码解释java 虚拟机栈的全过程

 

 (1)主线程开始执行,开辟一份栈空间

(2)main 方法开始执行,生成main 方法的栈帧

(3)new 对象,在堆空间生成一个对象,并在栈帧地局部变量表中生成一份指针

(4)开始执行add 方法,生成add 方法的栈帧

(5)栈帧中包含的信息有:局部变量表,操作数栈(一个临时存储空间,用来计算)、动态连接、方法出口

(6)add 方法执行结束后,会出栈,然后mai'n 方法接着执行,而具体执行的行出是根据程序计数器来记录具体的行数

 

 四、方法区 jdk 1.7 和1.8 的区别

1.在j'd'k 1.7  中方法区叫做永久代,而1.8中叫元数据,元数据和永久代的区别是,元数据使用了物理机的直接内存,直接内存的好处是不容易发生内存溢出,缺点是会产生内存碎片,而永久带的缺点是不好规划内存空间大小。

2.方法区中存放的数据是类的class 信息,包括:类的加载器引用;常量池、字段,每个字段的类型、修饰符、名字等;方法数据和方法代码

 

五、栈帧的动态链接

1.动态链接:方法对象的地址,动态链接是找到正确方法的入口,也就找到了对应的字节码指令,然后才有后来进栈出栈的执行

2.动态链接指在类的装载过程中不能通过符号引用专为直接引用,而在运行时才知道的,比如接口回调、多态、重载等

六、jvm 堆的内存分布

 

1.堆内存分为新生代和老年代,新生代分为Eden 区、from 区、to 区,内存回收时通过不断的切换from 和to 来回倒腾

 七、对象在jvm中的内存分布

1.jvm 中的内存分布主要包括四大部分:mark word (8字节),类型指针(压缩后4字节),实例数据,对齐填充

2.通过以下方式查看对象的内存分布

import com.sl.spring.framework.beans.SLBeanDefinition;
import org.openjdk.jol.info.ClassLayout;


public class test {
    public static void main(String[] args) {
        SLBeanDefinition beanDefinition=new SLBeanDefinition();
        System.out.println(ClassLayout.parseInstance(beanDefinition).toPrintable());
    }
}

 

 2.mark word 内存分布:hash 值、GC 分代年龄、锁等信息

 

 

八、jvm 垃圾回收算法

1.标记清除算法:通过可达性算法,标记哪些可达的对象,然后清除未标记的对象

2.标记清除算法(复制法):先将可达的对象复制到另一块区域,然后再清除

3.标记清除整理算法:

 

4.几种不同的垃圾回收期算法

 

 

 5。垃圾回收过程中存在的问题:

1)垃圾回收线程和用户线程同时运行会存在两个问题,1,该回收的没有回收;2,不该回收的回收了,3,如果 stop world 则会出现停顿

2)针对上面的问题,有两个解决办法 1,垃圾回收线程执行时,停止整个世界(其他业务线程停止)2,两种线程一部分过程并行,一部分同步,如,标记的时候只标记gc root ,然后再做一次标记,最后一起结束(这里有点绕),需要一个图;3,多次垃圾回收,每次回收一点一点,这样导致吞吐量降低(G1 垃圾收集器)

 九、jvm 调优及调优工具

posted @ 2021-01-26 13:58  狭路相逢智者胜  阅读(117)  评论(0编辑  收藏  举报