【技术积累】Java中的JVM【一】

博客 动态
0 317
羽尘
羽尘 2023-06-07 17:10:32
悬赏:0 积分 收藏

【技术积累】Java中的JVM【一】

什么是JVM

JVM英文全称为Java Virtual Machine,中文意为Java虚拟机。JVM是一种能够执行Java语言编写的程序的虚拟机器,它首次作为Java语言的一部分,后来又被移植到了许多平台上。

JVM可以执行Java字节码,即Java源代码经过编译后生成的二进制中间代码。JVM根据字节码指令来执行程序,这就使得Java程序跨平台,在不同的操作系统上运行时不需要修改源代码。JVM本身也是跨平台的,因为JVM实际上就是使用底层机器代码实现的软件层,因此只需安装相应平台的JVM即可。

JVM的主要组件包括:

  1. 类加载器:负责将.class二进制文件转换为在运行时可以被JVM识别的类对象。

  2. 运行时数据区:包括方法区、虚拟机栈、本地方法栈、堆等。Java程序在运行时需要占用这些区域中的内存。

  3. 执行引擎:负责执行字节码指令。

  4. 本地方法接口:使得Java程序可以调用本地方法,也就是使用C或C++重新编写的底层程序。

JVM为Java语言提供了许多高级特性,这些特性包括垃圾回收、异常处理、线程控制和动态代码加载。因此,JVM是许多Java开发者不可缺少的工具,也是Java语言的核心组件之一。

JVM是如何执行Java程序的?

JVM(Java Virtual Machine)是Java程序的运行环境,负责将Java代码转换为机器可以执行的代码。JVM执行Java程序的过程如下:

  1. 读取并解析字节码文件:JVM读取.class文件并将其解析为JVM可以理解的指令集。这些指令被存储在方法区(Method Area)中。

  2. 加载类:JVM根据程序需要动态地加载类。当需要使用某个类时,JVM会检查该类是否已经加载过,如果没有则JVM会从文件系统或网络中加载该类。

  3. 程序计数器指向当前指令:JVM中的程序计数器(Program Counter)指向当前正在执行的指令。在执行指令之前,程序计数器先指向该指令的地址。

  4. 执行指令集:JVM通过解释器或即时编译器来执行指令集。解释器逐条解释指令并执行,而即时编译器将整段指令编译成本地代码后再执行。执行指令集时,JVM还需要进行内存分配、垃圾回收等操作。

  5. 程序计数器指向下一条指令:执行完一条指令后,程序计数器会指向下一条指令的地址。这个过程不断循环,直到程序结束或异常抛出。

总之,JVM负责将Java程序转换成机器可以执行的代码,并提供运行时环境。JVM的执行过程中,会加载类、解释和执行指令集、内存分配和垃圾回收等操作。

什么是JIT编译器?

JIT(Just-In-Time)编译器是一种动态编译器,它在程序运行时将字节码翻译为本地机器代码。在JIT编译器中,代码被逐行解释器执行,当某些代码被频繁调用时,JIT编译器将这些代码编译成本地机器代码以提高执行效率。这种编译方式可以使程序在第一次运行时速度较慢,但在后续运行时速度会显著提高。JIT编译器常用于Java虚拟机等动态语言环境中。

JVM的内存模型是什么样子的?

JVM的内存模型是基于Java程序运行时内存的管理结构,主要分为以下几个部分:

  1. 程序计数器:每个线程都有一个程序计数器,用于记录当前线程执行的字节码行号。

  2. 虚拟机栈:每个线程都有一个虚拟机栈,用于存储方法执行时的局部变量表、操作数栈、动态连接和方法返回值等信息。

  3. 堆:JVM运行时动态分配的内存区域,用于存储Java对象和数组。

  4. 方法区:用于存储类信息、常量、静态变量、即时编译器编译后的代码等数据。

  5. 本地方法栈:与虚拟机栈类似,用于存储本地方法的信息。

在JVM中,堆是唯一一个被所有线程共享的内存区域,而每个线程都有自己的程序计数器、虚拟机栈和本地方法栈。同时,方法区也是被所有线程所共享的。JVM的内存模型为Java程序提供了良好的内存管理机制,能够有效地提高程序的性能和安全性。

什么是垃圾回收器?

JVM中的垃圾回收器是一种自动内存管理机制,它负责回收在程序中不再被使用的对象,并将这些内存释放回给操作系统。垃圾回收器通过扫描引用关系来确定哪些内存是“垃圾”,并将其标记为可回收。它可以大大减少程序员手动释放内存的工作量,提高程序的安全性和可靠性,但也会在一定程度上影响程序的性能。JVM中有很多不同类型的垃圾回收器,例如标记清除垃圾回收器、复制垃圾回收器、标记整理垃圾回收器等。这些垃圾回收器有不同的实现方式和适用场景,程序员需要根据需求选择合适的垃圾回收器。

下面是一个使用Java语言的代码示例,演示垃圾回收器如何回收无用对象。

public class GarbageCollectionExample {
  public static void main(String[] args) {
    // 创建一个对象
    Person p = new Person();
    
    // 将对象设置为null,表示不再引用该对象
    p = null;
    
    // 垃圾回收器会在这里回收无用对象
  }
}

class Person {
  // 将在这里添加Person类的属性和方法
}

在上述示例中,创建了一个名为Person的类,并实例化了一个对象p。然后将p设置为null,表示不再引用该对象。当垃圾回收器检测到该对象没有任何引用变量引用时,就会回收该对象并释放其占用的内存。

JVM中什么是强引用、软引用、弱引用、虚引用?

JVM中的四种引用类型:

  1. 强引用(Strong Reference):指向对象的引用,即使内存不足,JVM也不会回收被强引用关联的对象。强引用通常使用普通的Java对象引用来定义。
  1. 软引用(Soft Reference):软引用关联的对象会在内存不足的情况下被回收,也就是说只有当JVM发现一个对象只有软引用关联时,才会在内存不足时清除该对象。软引用通常使用SoftReference来定义。
  1. 弱引用(Weak Reference):弱引用关联的对象在JVM进行垃圾回收时,无论内存是否充足都会被回收。弱引用通常使用WeakReference来定义。
  1. 虚引用(Phantom Reference):虚引用关联的对象与弱引用关联对象的回收时机相同,但是虚引用必须和一个引用队列(ReferenceQueue)一起使用。虚引用通常使用PhantomReference来定义。
public class ReferenceExample {
    public static void main(String[] args) {
        // 强引用
        Object strongRef = new Object();

        // 软引用
        SoftReference<Object> softRef = new SoftReference<>(new Object());

        // 弱引用
        WeakReference<Object> weakRef = new WeakReference<>(new Object());

        // 虚引用
        ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
        PhantomReference<Object> phanRef = new PhantomReference<>(new Object(), refQueue);

        // 尝试回收
        System.gc();

        // 判断是否回收成功
        System.out.println(strongRef);
        System.out.println(softRef.get());
        System.out.println(weakRef.get());
        System.out.println(phanRef.get());
    }
}

JVM如何加载和查找类文件?

JVM加载和查找类文件的过程如下:

1.类加载器的工作:JVM负责从文件系统、JAR包或网络中加载类文件,并交给类加载器去加载。类加载器通常有四种:

  • 引导类加载器:负责加载JVM自身需要的类,如java.lang包中的类。
  • 扩展类加载器:负责加载JRE的扩展目录中的类。
  • 应用程序类加载器:负责加载应用程序中的类。
  • 用户自定义类加载器:负责加载用户自定义的类。

2.类文件的查找:类加载器会按照类的完全限定性类名(Fully Qualified Class Name,FQCN)去查找类文件。类的FQCN即包名+类名。

3.类文件的加载:当类加载器找到并读取了类文件后,JVM会根据类文件的结构创建一个表示该类的Class对象,并将其存放在JVM内部的方法区中,即类的元数据区。这个Class对象包含了该类的所有信息,如类名、类的修饰符、字段、方法等。

4.类的初始化:当类文件被加载后,JVM并不立即执行静态代码块和静态变量的默认初始化赋值,而是等待需要被初始化类的首次主动使用时才执行。

5.类的链接:为了使类能够正确执行,JVM需要对类进行链接。链接分为三个阶段:

  • 验证(Verification):验证类文件是否符合JVM规范。包括文件格式、字节码验证、符号引用验证、访问权限验证等。
  • 准备(Preparation):为类的静态变量分配内存,并设置默认初值。
  • 解析(Resolution):将类的符号引用解析为直接引用(如类或接口的全限定名解析为该类或接口的Class对象引用)。

6.类的使用:当一个类被加载、链接和初始化后,就可以被使用了。类的使用包括创建对象、调用方法、访问静态变量、执行静态代码块等。

JVM的性能调优需要注意哪些点?

JVM的性能调优需要注意以下几个点:

  1. 堆内存设置:JVM的堆大小设置对系统的性能影响很大,应该根据实际情况进行适当的调整。

  2. 垃圾回收设置:垃圾回收机制对系统的性能影响也非常大,应该根据应用的负载情况和内存使用情况进行适当的调整。

  3. 线程池设置:线程池的大小设置影响系统的并发能力和性能,应根据实际情况进行适当调整。

  4. JVM参数设置:JVM提供了很多配置参数,如内存分配、GC算法和堆大小等,应根据实际情况进行适当调整。

  5. 应用代码优化:应用的代码质量和设计对系统的性能也有影响,应该进行优化以提高系统的性能。

  6. 系统资源配置:系统的硬件资源配置也对系统的性能有较大的影响,应根据实际情况进行适当的调整。

如何监控JVM的运行状态?

可以通过以下几种方式来监控JVM的运行状态:

  1. JVisualVM:JVisualVM是一个监控和分析JVM的工具,可以查看内存使用、线程状态、GC情况、类加载等信息。需要在JDK的bin目录下执行jvisualvm命令启动。

  2. jstat:jstat是JVM自带的监控工具,可以查看JVM的堆、非堆内存使用情况、GC情况等。通过命令行方式运行。

  3. JMX:JMX是Java Management Extension的简称,可以通过JMX接口来监控和管理Java应用程序。可以使用JConsole等工具查看JVM的运行状况。

  4. 第三方工具:如AppDynamics、New Relic等都是常用的监控工具,可以通过集成agent来监控JVM的运行状态。

JVM如何保证Java程序的安全性?

JVM(Java虚拟机)可以保证Java程序的安全性,主要体现在以下几个方面:

  1. 类加载机制:JVM在程序运行时会将需要的类加载到内存中,并进行校验、解析和初始化,确保类的可靠性和正确性。如果类有被篡改或不正确的地方,JVM在加载时会直接抛出异常,防止不安全的代码被执行。

  2. 内存管理:JVM会提供内存分配、回收和访问保护等功能,防止程序出现内存泄露或越界访问等安全问题。

  3. 安全管理器:JVM可以通过安全管理器(Security Manager)实现对Java程序进行访问控制,限制程序对系统资源的访问,防止恶意代码执行或对系统造成危害。

  4. 字节码校验:在将Java代码编译成字节码之前,编译器会对代码进行各种检查,检验其是否符合Java语言规范和安全要求。JVM在执行字节码时会再次对其进行验证,确保代码的安全性。

  5. 安全沙箱:JVM还提供了安全沙箱(Security Sandbox)机制,将Java程序运行在一个独立的安全环境中,能够限制其对文件系统、网络等系统资源的访问,从而防止恶意代码对系统的攻击。

posted @ 2023-06-07 15:44  天佑1  阅读(17)  评论(0编辑  收藏  举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员