Java面试题冲刺第二十一天–JVM

JVM(Java Virtual Machine)即Java虚拟机,是Java语言的运行环境,负责将Java字节码文件转换为机器指令执行。

Java面试题冲刺第二十一天--JVM

一、了解JVM

1. JVM的概念

JVM(Java Virtual Machine)即Java虚拟机,是Java语言的运行环境,负责将Java字节码文件转换为机器指令执行。

2. JVM的内部结构

JVM的内部结构分为三个部分:类加载器,运行时数据区,执行引擎。

2.1 类加载器

用来加载类文件,包括如下几种类型:

  1. Bootstrap ClassLoader:启动类加载器,用来加载JVM自身的类,在Classpath中找不到。

  2. Extension ClassLoader:扩展类加载器,用来加载JRE中的类库,在Classpath中找不到。

  3. System/Application ClassLoader:系统类加载器,用来加载应用程序中的类,在Classpath中找到。

2.2 运行时数据区

JVM运行时数据区分为如下几个部分:

  1. 程序计数器:当前线程执行的字节码的行号记录器。

  2. Java虚拟机栈:每个线程独享一块区域,用来存储方法执行过程中的局部变量、操作数栈、动态连接、方法出口等信息。

  3. 本地方法栈:用来执行本地方法的调用,如C语言代码等。

  4. Java堆:存储Java对象的区域,由新生代和老年代两个子区域组成。

  5. 方法区:用来存储已加载的类信息、常量、静态变量等等。

2.3 执行引擎

执行引擎是JVM的最核心的部分,它负责将字节码转换为机器指令执行。

二、JVM的垃圾回收

1. 垃圾回收的概念

垃圾回收就是在程序运行过程中,GC(Garbage Collector,垃圾回收器)自动释放已经不再需要的内存。

2. 垃圾回收算法

目前主流的垃圾回收算法包括如下几种:

  1. 标记-清除算法:先标记所有需要回收的对象,再统一进行回收。

  2. 复制算法:将内存分为两个区域,每次使用其中一个区域,当这个区域使用完后,将存活的对象复制到另一个区域中。

  3. 标记-整理算法:在标记完成之后,将存活的对象向一端移动,然后在端点之后所有的空间全部释放。

3. 垃圾回收器

垃圾回收器的种类有很多,包括:

  1. Serial收集器:单线程的独占式收集器,适合于小型程序。

  2. ParNew收集器:Serial收集器的多线程版本,适合于多CPU的环境。

  3. CMS收集器:并发标记清除收集器,支持低延迟的垃圾回收。

  4. G1收集器:并发标记整理收集器,支持更大的堆,更高效的垃圾回收。

三、关于内存分配和回收

1. Java堆的内存划分

Java堆分为新生代和老年代两个区域,新生代又分为Eden区和Survivor区(From和To)。

2. 内存分配和回收策略

内存分配和回收策略有如下几种:

  1. 对象优先在Eden区分配,如果Eden区没有足够空间,则将存活的对象放进Survivor区,如果Survivor区满了,采用复制算法将存活对象复制到另一个Survivor区中,如果两个Survivor区都满了,则采用老年代进行分配。

  2. 大对象直接进入老年代,如一个大的数组或字符串等。

  3. 长期存活的对象将进入老年代,设置阈值参数,当对象在Survivor区中熬过了15轮,则将对象移动到老年代中。

3. 内存泄漏

内存泄漏是指程序中存在不能访问的对象,但是却仍然占用着内存,导致程序运行过程中内存耗尽。

四、示例说明

示例一

编写如下代码:

public void foo() {
    String str = "hello";
    System.out.println(str);
}

首先,JVM会在程序启动时加载java.lang.Object类,还会预先加载其他常用的类。

然后,JVM会在当前线程的Java虚拟机栈中压入一个栈帧,每个栈帧中包含了局部变量、操作数栈、调用者栈帧地址等信息。

foo()方法执行到String str = "hello"语句时,JVM会在栈帧的局部变量表中分配一个String类型变量str,并将值设置为hello

最后,在System.out.println(str)语句执行时,JVM会调用System.out对象的println()方法,并将str作为参数传递过去。

示例二

编写如下代码:

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", and I am " + age + " years old.");
    }
}

在Java虚拟机中,会有一个类加载器,用来加载所有的类。

在程序执行到Person person = new Person("张三", 20)语句时,JVM会先检查是否已经加载了Person类,如果没有则使用类加载器加载该类。

当类被加载之后,JVM会在堆中分配一个内存区域作为Person类型变量的实例对象。这个区域包含了对象的所有属性值,如nameage等。

最后,当程序执行到person.sayHello()时,JVM会执行该方法,其中nameage属性值会作为参数传递到System.out.println()方法中,实现输出信息的功能。

本文标题为:Java面试题冲刺第二十一天–JVM

基础教程推荐