JVM体系结构概述(一)

一、app.java程序运行具体的流程

假设我们现在有app.java这个程序要运行,那么具体的流程到底是怎么样的呢?

我们会先运行 javac app.java, 然后这个程序会被编译,产生了app.class这个file,然后我们会用java app去执行整个程序。下面几幅图解释了这背后发生的事。

步骤一:

这是一个简化的流程:class loader先将开发者编译的app.class和基本的.class文件load到RAM里面,这过程也load了其它基本的.class文件: 比如说,String对应的的.class, collection 的 .class,或者object的 .class文件。

经过了class loader的处理后,产生了byte code instruction, 放到execution engine里面, 然后execution engine会通过Native method calls来执行程序。

步骤二:

这个流程还可以分成3个主要成分去分析

  1. Loader subsystem
  2. Runtime data area
  3. Execution engine

下面会一一介绍每个部分的功能。

(1)Loader subsystem

loader subsystem:

  1. load:

    1. Application class loader: 主要是load开发者的.class文件
    2. Bootstrap class loader: load JAVA API 的 .class文件
  2. link

    1. Verify, 主要检查class和interface结构的正确性
    2. Prepare, 用于allocate memory给.class file里面的static variables
    3. Resolve, 主要是将symbolic reference改成具体的一个值
  3. initialize:

    1. 主要进行class和interface的初始化

(2)Run time data area


  1. Method(class) data: 主要用于储存class的定义,另外还有method data, field, 和method的code
  2. Heap: 主要用于储存程序运行时所产生的Object
  3. PC Register: 全称是program counter register, 主要用于存放下一个JVM instruction的reference
  4. JAVA Stack:主要用于储存method运行时的数据,
  5. Native method stack: 这是native method被执行的地方. Native method就是用别的语言写出来的编程语言

(3)Execution Engine

  1. Interpreter:主要功能是读bytecode,然后执行相对应的instructions.
  2. JIT(Just-in-time) Compiler:这个部分主要是用以优化execution engine的性能,一般execution engine会先用interpreter去解释bytecode, 然后执行对应的命令。在很多时候,JIT compliler可以将相类似的bytecode都翻译成native code,然后直接运行。直接执行native code会比bytecode快。
  3. Hotspot profiler: 这个部分也是用来优化性能的,当某些method被多次使用时,Hotspot这个部分就会用profiler去记录那些method所对应的native code, 这样就可以直接用native code而不是byte code了。
  4. Garbage collector: 这个部分主要负责内存的管理,当程序中的object不再被用的时候,garbage collector会将其删除。

二、JVM位置

三、JVM体系结构

图示说明:

1.灰色区域不会有垃圾回收;

2.暗黄色区域会发生垃圾回收,99%发生在堆中。

(1)类装载器ClassLoader

负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定

类装载器的运行示意图:


(2)类装载器ClassLoader的类型(4种)

虚拟机自带的加载器(3种)

•启动类加载器(Bootstrap)C++

•扩展类加载器(Extension)Java

•应用程序类加载器(App)Java,也叫系统类加载器,加载当前应用的classpath的所有类

需要进行如下两点说明:

第一点:

sun.misc.Launcher它是一个java虚拟机的入口应用。

​ 某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载

// 自定义的类
class Demo{

}
public class TestClassLoader {

    public static void main(String[] args) {
        // 自带的
        Object o = new Object();
        System.out.println("===============================   Object  ClassLoader   ===============================");

        System.out.println(o.getClass().getClassLoader());
        System.out.println("===============================   Demo  ClassLoader   ===============================");

        Demo demo = new Demo();
        System.out.println("demo的爷爷 : " + demo.getClass().getClassLoader().getParent().getParent());
        System.out.println("demo的爸爸 : " + demo.getClass().getClassLoader().getParent());
        System.out.println("demo : " + demo.getClass().getClassLoader());
    }
}

程序输出结果:

===============================   Object  ClassLoader   ===============================
null
===============================   Demo  ClassLoader   ===============================
demo的爷爷 : null
demo的爸爸 : sun.misc.Launcher$ExtClassLoader@2503dbd3
demo : sun.misc.Launcher$AppClassLoader@18b4aac2

Process finished with exit code 0

第二点:

自顶向下加载class文件,先到先得。什么意思呢?

举个例子说明:

我们自定义一个String类,和JVM自带的String类再同一个包下,那么此时就会有冲突。此时,我们遵循自顶向下加载原则,对于后加载的class,全部忽略,以防止恶意代码对于源码的修改。

用户自定义加载器 (第4种)

Java.lang.ClassLoader的子类,用户可以定制类的加载方式。

参考链接

本文主要整理自互联网,主要是便于自己复习知识所用,侵权联系删除,以下为原文参考链接!

【1】JVM architecture介绍
【2】尚硅谷jvm教程

猜你喜欢

转载自www.cnblogs.com/ch-forever/p/10223763.html