一张图学会JVM内存模型和运行原理

先上一张重要的原理图,这里挂上原理图的psd文件,方便大家有了自己的理解后在里面增加修改自己理解的内容。psd文件地址:https://download.csdn.net/download/qq_14868375/12922475

理解jvm主要要理解两个内容

1、Java类的编译、加载和执行。这是今天篇文章主要讲的内容。

2、JVM的内存管理和垃圾回收机制。这个主要讲的是堆的的管理,是下一篇文章主要讲的内容。

今天先讲Java类的编译、加载和执行。

1. Java类的编译过程

这是由*.java源码文件转为 .class二进制字节码文件的过程。
我们编写好的源代码,就是
.java文件。使用“javac test.java”就可以编译test.java文件。

编译过程主要有三步:

1、词法分析和输入到符号表

2、注解处理

3、语义分析和生成字节码

详细过程:

源代码文件*.java -> 词法分析器 -> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> JVM字节码文件*.class 

最后剩成的JVM字节码文件,使用命令“javap -c test”可以查看test.class的字节码信息,主要包含三项内容:

1、结构信息:class文件相关信息。

2、元数据:Java源码中的声明和常量信息。

3、方法信息:Java源码语句和表达式对应的字节码。

2. 类加载机制

加载指的是将类的class文件读入到内存。

2.1 类加载器分类

1、根加载器BootstrapClassLoader,负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类。

2、扩展加载器ExtensionClassLoader,负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

3、系统应用加载器APPClassLoader,负责记载classpath中指定的jar包及目录中class。

4、用户自定义加载器CustomerClassLoader,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。

2.2 类加载的时机

1、创建类的实例,也就是new一个对象

2、访问某个类或接口的静态变量,或者对该静态变量赋值

3、调用类的静态方法

4、反射(Class.forName("com.lyj.load"))

5、初始化一个类的子类(会首先初始化子类的父类)

6、JVM启动时标明的启动类,即文件名和类名相同的那个类    

2.3 类加载机制

1、双亲委派机制。

双亲委派机制,其工作原理的是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己才想办法去完成。

双亲委派机制的优势:采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

2、全盘负责机制。

所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入。

3、缓存机制

缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓冲区中。这就是为很么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因。

2.4类加载过程

类的加载过程基本为连接、初始化两个过程。

1、链接

连接(linking)包括三个部分:

  • 验证verifying:验证类符合Java规范和JVM规范,和编译阶段的语法语义分析不同。

  • 准备preparing:为类的静态变量分配内存,初始化为系统的初始值。(不初始化静态代码块)。对于final static修饰的变量,直接赋值为用户的定义值。

  • 解析resolving:将符号引用(字面量描述)转为直接引用(对象和实例的地址指针、实例变量和方法的偏移量)

2、初始化

初始化类的静态变量和静态代码块为用户自定义的值。非静态类在实例化类,初始化Java堆中的对象。

2.5类方法的执行机制

JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。

JVM执行class字节码,线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值