JVM如何工作 - JVM架构?(翻译自GeeksforGeeks)

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

Java应用程序称为WORA(Write Once Run Anywhere)。这意味着程序员可以在一个系统上开发Java代码,并且可以期望它在任何其他支持Java的系统上运行而无需任何调整。由于JVM,这一切都是可能的。

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


 

JVM

 

类加载器子系统
它主要负责三个活动。

  • 载入中
  • 链接
  • 初始化

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

  • 加载类及其直接父类的完全限定名称。
  • 无论的.class文件与类或接口或枚举
  • 修改器,变量和方法信息等

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

filter_none

编辑

play_arrow

brightness_5

// 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文件,只创建一个 Class对象。

学生s2 =新学生(); 
// c2将指向
// c1指向的同一对象
Class c2 = s2.getClass(); 
的System.out.println(C1 == C2); //真的

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

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

初始化:在此阶段,所有静态变量都分配有在代码和静态块(如果有)中定义的值。这在类中从上到下执行,在类层次结构中从父到子执行。
一般来说,有三个类加载器:

  • Bootstrap类加载器:每个JVM实现必须有一个引导类加载器,能够加载受信任的类。它加载JAVA_HOME / jre / lib目录中的核心Java API类。此路径通常称为引导路径。它以C,C ++等本地语言实现。
  • 扩展类加载器:它是bootstrap类加载器的子代。它加载扩展目录JAVA_HOME / jre / lib / ext(扩展路径)中存在的类或java.ext.dirs系统属性指定的任何其他目录。它由sun.misc.Launcher $ ExtClassLoader类在java中实现。
  • 系统/应用程序类加载器:扩展类加载器的子代。它负责从应用程序类路径加载类。它在内部使用映射到java.class.path的Environment Variable。它也是由sun.misc.Launcher $ AppClassLoader类在Java中实现的。

filter_none

编辑

play_arrow

brightness_5

// 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遵循委托 - 层次结构原则来加载类。系统类加载器委托加载请求到扩展类加载器和扩展类加载器委托请求到引导程序类加载器。如果在boot-strap路径中找到类,则加载类,否则请求再次转移到扩展类加载器,然后再转移到系统类加载器。最后,如果系统类加载器无法加载类,那么我们得到运行时异常java.lang.ClassNotFoundException

JVM

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

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

 

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

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

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

JVM2

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值