JVM架构


JVM架构文章插图
> JVM- Architecture [pic credit: google]
同志们好 ,
今天 , 我们期待对JVM体系结构的组成及其所包含的组件有一个简短的了解 。在这里 , 我们将了解所有组件的工作或说出的作用 。因此 , 让我们开始吧!
JVM体系结构分为三个主要部分:
· 类加载器子系统
· 运行时数据区
· 执行引擎
类加载器子系统Java类加载器将类加载到JVM中 。所有虚拟机都包含一个嵌入到虚拟机中的类加载器 , 该嵌入式加载器称为原始类加载器 。此类默认情况下实现loadClass()的默认实现 。
在以下两种情况下加载类:执行新的字节码和字节码对类进行静态引用时 , [我们将在进一步的主题中对此进行详细讨论] 。
Java的动态类加载功能由该类加载器子系统处理 。它基本上在运行时加载 , 链接和初始化类文件 。
Java类加载器基于以下三个原则:
· 委托原则:该原则将类加载请求转发到其父类加载器 。仅当父级找不到或加载类时 , 才加载该类 。
· 可见性原则:此原则仅向子类加载器提供可见性 , 以查看所有类均由父类加载 , 反之则不 。
· 唯一性原则:该原则允许任何类只能加载一次 。委托原则可以很容易地实现这一点 , 它可以确保父类加载的类不会被子类重新加载 。
类加载器的类型:类加载器根据加载类的路径分为以下几种类型 。
· Bootstrap类加载器:它是所有类加载器的父级 。它从Core类加载类文件 。也称为原始类加载器 。它从rt.jar文件即jre / lib / rt.jar加载类
· 扩展类加载器:它负责加载ext文件夹内的类 , 即jre / lib
· 系统/应用程序类加载器:它负责从应用程序类路径加载类 。
JVM的工作如下 , 系统类加载器将加载请求委派给扩展类加载器 , 扩展类加载器再将请求委派给Bootstrap类加载器 。如果在Bootstrap类加载器中检测到该类 , 则该类将被加载 , 否则请求将再次传输到扩展类加载器; 但是 , 如果找不到该类 , 则会得到一个运行时异常java.lang.ClassNotFoundException 。
运行时数据区运行时数据区域分为方法区域 , 堆区域 , 堆栈区域 , PC寄存器 , 本机方法堆栈 。
方法区域:所有类级别的信息 , 即直接父名称 , 类名称 , 方法和变量都存储在方法区域中 。它包含在类以及对象和接口的初始化中使用的元素 。每个JVM分配一个方法区 。它是共享资源 。它在所有线程中都是通用的 。
堆区:所有对象的详细信息存储在堆区中 。通过任何线程访问时 , 堆区域又分为年轻一代 , 旧一代和PermGen [永久一代] 。创建对象时 , 它首先访问Young Generation(伊甸园空间) , 当它变老时 , 它将进一步移入Old Generation 。所有的静态变量和实例变量都存储在PermGen中[将在垃圾回收主题中对此进行详细讨论] 。每个JVM分配一个堆区 。它也是所有线程共有的共享资源 。
堆栈区:JVM为每个单个线程创建一个运行时堆栈 。堆栈中存在的每个块都称为激活记录/堆栈帧 , 其中包含所有方法调用 。所有本地变量调用都存储在相应的帧中 。线程终止后 , JVM将破坏其堆栈 。它不是共享资源 。当堆栈已满时 , 它将引发stackOverFlow错误 。
PC寄存器:存储线程的当前执行指令的地址 。每个线程都有特定的PC寄存器 。它基本上会跟踪指令 。
本机方法堆栈:本机方法是用Java以外的语言编写的方法 。将本机方法信息存储到其中 。每个线程都拥有其本机方法Stack 。它与堆栈区域相同 , 除了用于本机方法 。
执行引擎(Execution Engine)它逐行执行.class(字节码)文件 , 进一步分为:解释器 , 即时编译器和垃圾收集器 。 解释器解释字节码 , 然后执行该代码 。 这里出现的问题是 , 任何方法被调用的次数就是该次数 , 将需要解释器 。 如我们先前的文章所述 , JIT编译器有助于提高解释器的效率 。 它编译整个字节码并将其更改为本机代码 , 以便每当解释器看到重复的方法调用时 , JIT编译器都会提供直接可用的本机代码 , 因此不需要重新解释 。 通过提高效率 。JIT编译器是一种算法 , 可以帮助我们进行编译和解释 。 对于冗余代码 , 它的性能更好 , 但是在将字节码转换为本地代码时 , 可能会增加运行时开销 。 作为JIT编译器一部分的Profiler负责标识重复的方法调用 。JIT编译仅适用于重复调用的方法 , 而不适用于每个方法 。 垃圾收集器的功能是销毁未引用的对象 , 即释放正在运行的应用程序不再需要的任何内存 。 [将有专门针对GC的文章]