JVM是如何工作的?– JVM体系结构是怎么样的?

2021年3月25日12:45:53 发表评论 752 次浏览

JVM(Java虚拟机)充当运行Java应用程序的运行时引擎。 JVM是实际上称为主要Java代码中存在的方法。 JVM是JRE(Java运行时环境)的一部分。

Java应用程序称为WORA(可在任何地方写入一次)。这意味着程序员可以在一个系统上开发Java代码, 并且可以期望它在任何其他启用Java的系统上运行, 而无需进行任何调整。由于JVM, 所有这些都是可能的。

当我们编译一个.java文件, 。类具有相同类名的文件(包含字节码).java文件由Java编译器生成。这个。类文件在运行时会进入各个步骤。这些步骤共同描述了整个JVM。

虚拟机

类加载器子系统

它主要负责三项活动。

  • 载入中
  • 连结中
  • 初始化

正在加载:类加载器读取。类文件, 生成相应的二进制数据并将其保存在方法区域中。对于每个。类文件, JVM将以下信息存储在方法区域中。

  • 加载的类及其直接父类的全限定名称。
  • 是否。类文件与类或接口或枚举有关
  • 修饰符, 变量和方法信息等

加载后。类在文件中, JVM创建类型为Class的对象来表示该文件在堆内存中。请注意, 此对象的类型为在java.lang包。程序员可以使用此Class对象来获取类级别的信息, 例如类名称, 父名称, 方法和变量信息等。要获取此对象引用, 我们可以使用getClass()的方法Object类。

// A Java program to demonstrate working of a Class type
// object created by JVM to represent .class file in
// memory.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
  
// Java code to demonstrate use of Class object
// created by JVM
public class Test
{
     public static void main(String[] args)
     {
         Student s1 = new Student();
  
         // Getting hold of Class object created
         // by JVM.
         Class c1 = s1.getClass();
  
         // Printing type of object using c1.
         System.out.println(c1.getName());
  
         // getting all methods in an array
         Method m[] = c1.getDeclaredMethods();
         for (Method method : m)
             System.out.println(method.getName());
  
         // getting all fields in an array
         Field f[] = c1.getDeclaredFields();
         for (Field field : f)
             System.out.println(field.getName());
     }
}
  
// A sample class whose information is fetched above using
// its Class object.
class Student
{
     private String name;
     private int roll_No;
  
     public String getName()  {  return name;   }
     public void setName(String name) { this .name = name; }
     public int getRoll_no()  { return roll_No;  }
     public void setRoll_no( int roll_no) {
         this .roll_No = roll_no;
     }
}

输出如下:

Student
getName
setName
getRoll_no
setRoll_no
name
roll_No

注意 :每次加载。类仅文件一创建了Class对象。

Student s2 = new Student();
// c2 will point to same object where 
// c1 is pointing
Class c2 = s2.getClass();
System.out.println(c1==c2); // true

连结:执行验证, 准备和(可选)解决方案。

  • 验证:它确保了正确性。类文件, 即它检查此文件是否由有效的编译器正确格式化和生成。如果验证失败, 我们将获得运行时异常java.lang.VerifyError.
  • 制备:JVM为类变量分配内存, 并将内存初始化为默认值。
  • 解析度:这是用直接引用替换类型中的符号引用的过程。通过搜索方法区域以找到引用的实体来完成此操作。

初始化:

在此阶段, 将为所有静态变量分配在代码和静态块(如果有)中定义的值。在类中从上到下执行, 在类层次结构中从上到下执行。

通常, 有三种装载机:

  • 引导类加载器注意:每个JVM实现都必须具有一个引导类加载器, 该加载器能够加载受信任的类。加载存在于Java的核心Java API类JAVA_HOME / jre / lib目录。该路径通常称为引导路径。它以C, C ++等本地语言实现。
  • 扩展类加载器:是引导程序类加载器的子级。它加载扩展目录中存在的类JAVA_HOME / jre / lib / ext(扩展路径)或java.ext.dirs系统属性指定的任何其他目录。它是由Java实现的sun.misc.Launcher $ ExtClassLoader类。
  • 系统/应用程序类加载器:是扩展类加载器的子级。它负责从应用程序类路径加载类。它在内部使用映射到java.class.path的环境变量。它也由Java用Java实现。sun.misc.Launcher $ AppClassLoader类。
// Java code to demonstrate Class Loader subsystem
public class Test
{
     public static void main(String[] args)
     {
         // String class is loaded by bootstrap loader, and
         // bootstrap loader is not Java object, hence null
         System.out.println(String. class .getClassLoader());
  
         // Test class is loaded by Application loader
         System.out.println(Test. class .getClassLoader());
     }
}

输出如下:

null
sun.misc.Launcher$AppClassLoader@73d16e93

注意 :JVM遵循委派层次结构原则来加载类。系统类加载器将加载请求委托给扩展类加载器, 扩展类加载器将请求委托给引导类加载器。如果在引导路径中找到了类, 则将装入该类, 否则再次将请求传输到扩展类加载器, 然后再传输到系统类加载器。最后, 如果系统类加载器无法加载类, 则会得到运行时异常java.lang.ClassNotFoundException.

虚拟机

JVM内存

方法范围:

在方法区域中, 将存储所有类级别信息, 例如类名称, 直接父类名称, 方法和变量信息等, 包括静态变量。每个JVM只有一个方法区域, 它是共享资源。

堆面积:所有对象的信息都存储在堆区域中。每个JVM还有一个堆区。它也是共享资源。

堆放面积:JVM为每个线程创建一个运行时堆栈, 该堆栈存储在此处。该堆栈的每个块称为存储方法调用的激活记录/堆栈帧。该方法的所有局部变量都存储在其相应的框架中。线程终止后, 其运行时堆栈将被JVM破坏。它不是共享资源。

PC寄存器:存储线程当前执行指令的地址。显然, 每个线程都有单独的PC寄存器。

本机方法栈:对于每个线程, 将创建单独的本机堆栈。它存储本机方法信息。

jvm2

执行引擎

执行引擎执行

。类

(字节码)。它逐行读取字节码, 使用存在于各个存储区中的数据和信息并执行指令。它可以分为三个部分:

  • 口译员:逐行解释字节码, 然后执行。此处的缺点是, 当多次调用一种方法时, 每次都需要解释。
  • 即时编译器(JIT):用于提高解释器的效率。它编译整个字节码并将其更改为本地代码, 因此每当解释器看到重复的方法调用时, JIT都会为该部分提供直接的本地代码, 因此不需要重新解释, 从而提高了效率。
  • 垃圾收集器:销毁未引用的对象。有关垃圾收集器的更多信息, 请参阅垃圾收集器.

Java本机接口(JNI):

它是一个与本机方法库交互的接口, 并提供执行所需的本机库(C, C ++)。它使JVM可以调用C / C ++库, 并可以由特定于硬件的C / C ++库调用。

本机方法库:

它是执行引擎所需的本机库(C, C ++)的集合。

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: