JVM底层运行原理(上)

  jvm是java程序的运行环境,作为一名java程序员,是肯定要理解的。有不对的请留言,一定改。

1.JVM整体介绍

  • JVM 运行流程
    图中的源程序,不仅仅只有java,比如scale等,也可以作为源程序。
    java语音之所以是跨平台的,就是因为有JVM。
    JVM底层运行原理(上)_第1张图片

  • JVM整体结构
    主要由类加载器,运行时数据区,执行引擎,本地方法等组成。
    JVM底层运行原理(上)_第2张图片

2.JVM组成介绍

  • 类加载器(ClassLoader)
    jvm中有四类加载器,按优先级分别是启动类加载器(加载rt.jar),扩展类加载器(加载/lib/ext文件夹里面的jar),应用类加载器(我们的应用程序就是由它加载)和自定义类加载器。类加载采用的是双亲委派模型,双亲委派意思就是当加载一个类的时候,先由优先级高的加载器去加载,如果没找到就依次往下,也就是说任何一个类加载的时候都会到启动类加载器去判断是否可加载到,类加载器不是继承的关系,是组合的关系。JVM底层运行原理(上)_第3张图片
    类加载的过程:
    JVM底层运行原理(上)_第4张图片

加载:将class文件加载到内存,并将静态数据
执行引擎转化成方法区的运行时数据结构,在堆中生成一个java.lang.Class对象,作为方法区类数据的访问入口。
链接(验证,准备,解析):将二进制字节码转化为JVM的运行状态的过程。
验证:验证加载的类信息符合JVM规范;
准备:在方法区中为静态变量分配内存,并赋初始值.
解析:虚拟机中的符号引用转化为直接引用。
初始化:执行类的clinit方法,这个方法是由编译器收集静态变量和静态代码块赋值动作合并而成的;初始化一个类的时候会判断其父类是否初始化,如果没有会先触发父类的初始化;虚拟机会保证这个方法在多线程环境下的加锁和同步。创建一个对象数组,是不会触发这个对象初始化的。
运行时数据区:JVM底层运行原理(上)_第5张图片

程序计数器:当前线程执行的字节码的行号指示器,通过改变此指示器来选取下一个需要执行的字节码指令,(线程私有,唯一一个不会出现内存溢出的区域)。
方法区:存储类信息,常量,静态变量,方法字节码,编译器编译后的代码等数据,常说的“永久代”也是方法区的一部分;运行时常量池也是方法区的一部分用于存放编译期生成的各种字面量和符号引用,String.intern()方法可以在运行时动态将数据加入运行时常量池,jdk1.7及之后已经将字符串常量池从“永久代”中移到了堆中,jdk1.8已经后移除了“永久代”,改为了元数据存储,这个区域占用的不是虚拟机内存,而是native Memory来存储(线程共享)。
java虚拟机栈:每个方法在执行时就会创建一个栈帧,存储局部变量表、操作数栈、动态链接、方法出口等信息;方法执行就对应一个栈帧在jvm中入栈到出栈的过程;局部变量表在编译时就确定了大小;方法执行完就释放了(线程私有,如果栈的深度大于虚拟机所允许的深度,会出现stackOverFlow)。
本地方法栈:java本地(native)方法执行时的栈帧。
:存储对象和数组等,一般都采用分代收集算法,分为新生代(eden区,form survivor,to survivor)和老年代(线程共享,GC管理的主要区域);
在这里插入图片描述

参考资料:《深入理解java虚拟机》

你可能感兴趣的:(java)