JDK、JRE、JVM的区别 JVM工作原理

JDK,JRE和JVM之间的差异

要了解这三个之间的区别,让我们考虑下图。
区别
  • JDK - Java开发工具包(简称JDK)是一个工具包,它提供开发和执行(运行) Java程序的环境。JDK是一个工具包(或程序包),其中包括两件事
    • 开发工具(提供开发Java程序的环境)
    • JRE(执行Java程序)。
    注意: JDK仅由Java开发人员使用。
  • JRE - Java Runtime Environment(可以说JRE)是一个安装包,它提供在您的计算机上运行(不开发) Java程序(或应用程序)的环境。JRE仅由只希望运行Java程序(即系统的最终用户)的用户使用。
  • JVM - Java虚拟机(JVM)是​​JDK和JRE的非常重要的组成部分,因为它们既包含又内置在其中。无论使用JRE或JDK运行的任何Java程序进入JVM,JVM都负责逐行执行Java程序,因此它也称为解释器。
 

JRE和JDK如何工作?

JRE由什么组成? JRE由以下组件组成:
  • 部署技术,包括部署,Java Web Start和Java插件。
  • 用户界面工具包,包括抽象窗口工具包(AWT),Swing,Java 2D,可访问性,图像I / O,打印服务,声音,拖放(DnD)输入法
  • 集成库,包括接口定义语言(IDL),Java数据库连接性(JDBC),Java命名和目录接口(JNDI),远程方法调用(RMI),通过Internet Orb协议进行远程方法调用(RMI-IIOP)脚本
  • 其他基础库,包括国际支持,输入/输出(I / O),扩展机制,Bean,Java管理扩展(JMX),Java本机接口(JNI),数学,网络,覆盖机制,安全性,序列化Java for XML处理(XML JAXP)
  • Lang和util基本库,包括lang和util,管理,版本控制,zip,工具,反射,集合,并发实用程序,Java存档(JAR),日志记录,首选项API,引用对象正则表达式
  • Java虚拟机(JVM),包括Java HotSpot客户端服务器虚拟机
JRE如何工作? 为了了解JRE的工作原理,让我们考虑一个另存为Example.java的Java源文件。该文件被编译为一组字节码,该字节码存储在“ .class ”文件中。这里是“ Example.class ”。

编译时间

下图描述了在编译时执行的操作。
在运行时发生以下动作。
  • 类加载器
  • 类加载器加载执行程序所需的所有必要类。它通过将本地文件系统的命名空间与通过网络导入的命名空间分开来提供安全性。这些文件从硬盘,网络或其他来源加载。
  • 字节码验证器
  • JVM通过字节码验证程序放置代码,字节验证程序检查格式并检查非法代码。例如,非法代码是违反对象访问权限或违反指针实现的代码。

    字节码验证程序可确保代码符合JVM规范,并且不会违反系统完整性。
    运行
  • 解释者
  • 在运行时,字节码由解释器加载,检查和运行。解释器具有以下两个功能:
    • 执行字节码
    • 对基础硬件进行适当的调用
    两种操作都可以显示为:
    解释器和运行时
    要了解JDK和JRE之间的交互,请考虑下图。
    相互作用


     
 

JVM如何工作?

 

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

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

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

类加载器子系统 它主要负责三个活动。
  • 加载
  • 连接
  • 初始化

加载:类加载器读取.class文件,生成相应的二进制数据并将其保存在方法区域中。对于每个.class文件,JVM将以下信息存储在方法区域中。
  • 加载的类及其直接父类的全限定名称。
  • 无论是.class文件与类或接口或枚举
  • 修饰符,变量和方法等

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

// 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;
    }
}

Output:

Student
getName
setName
getRoll_no
setRoll_no
name
roll_No


Note : For every loaded .class file, only one object of Class is created.

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 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());
    }
}    

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

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

初始化:在此阶段,所有静态变量都分配有在代码和静态块(如果有)中定义的值。在类中从上到下执行,在类层次结构中从上到下执行。
通常,有三种装载机:
  • 引导程序类加载器:每个JVM实现都必须具有一个引导程序类加载器,能够加载受信任的类。它加载JAVA_HOME / jre / lib目录中存在的核心Java API类。该路径通常称为引导路径。它以C,C ++等本地语言实现。
  • 扩展类加载器:它是引导类加载器的子级。它将加载扩展目录JAVA_HOME / jre / lib / ext(扩展路径)或java.ext.dirs系统属性指定的任何其他目录中存在的类。它由sun.misc.Launcher $ ExtClassLoader类在Java中实现。
  • 系统/应用程序类加载器:它是扩展类加载器的子级。它负责从应用程序类路径加载类。它在内部使用映射到java.class.path的环境变量。它还由sun.misc.Launcher $ AppClassLoader类在Java中实现。

Output:

null
sun.misc.Launcher$AppClassLoader@73d16e93

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

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


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


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


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

Native method stacks :为每个线程创建单独的本机堆栈。它存储本机方法信息。

 

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

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

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


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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值