1. JVM的位置?

  1. JVM 就是做用 在操作系统上的虚拟机。JVM虚拟机上才可以运行Java程序,在不同系统中安装不同版本的JVM,所以Java实现了跨平台

2. JDK、JRE、JVM及JIT之间有什么不同?

  1. JVM: Java虚拟机, Java程序在JVM虚拟机上才可以运行,不同平台有不同版本的虚拟机,所以java实现了跨平台
  2. JRE: Java的基础类库,JRE包括Java虚拟机和Java程序所需的核心类库。
  3. JDK: Java的核心,JDK包括编译工具、和JRE基础类库
  4. 所以: JDK包含了JRE, JRE包含了JVM
  5. JIT: 即使编译, 当代码执行的次数超过一定的阈值时,会将Java字节码转换为本地代码.

3. java中会存在内存泄漏吗,请简单描述。

  1. 会。自己实现堆载的数据结构时有可能会出现内存泄露,

4. 32 位和 64 位的 JVM,int 类型变量的长度是多数?

  1. 32 位和 64 位的 JVM 中,int 类型变量的长度是相同的,都是 32 位或者 4个字节。

![3`]KWT)9C[(8HRKAN8H(JW.png](https://cdn.nlark.com/yuque/0/2022/png/21644188/1642420936385-dfb0c02d-4b7f-4fe7-b982-69db2c4ddfa9.png#clientId=ucc60d6ca-26bc-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=w5h6K&margin=%5Bobject%20Object%5D&name=3%60%5DKWT%299C%5B%288HRKAN8H%28JW.png&originHeight=494&originWidth=800&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38328&status=done&style=none&taskId=u3f3b9897-b5ef-404a-9fb8-a34db5a4f96&title=)
![Z%O]_A4[ZZ1UY}TYKO]QOK.png

5. 详细的介绍下程序计数器?(重点理解)

  1. 程序计数器就是寄存器。指的是程序执行过程,保存当前线程所正在执行的字节码指令的地址(行号)。
  2. 每个线程工作时都有独立的计数器,只为执行Java方法服务,执行Native方法时,程序计数器为空.

6. JNI是什么?

  1. JNI: java native interface 扩展java的使用,融合不同的编程语言为java所有.最终执行的时候, 通过JNI加载本地方法库中的方法。

7. 双亲委派

$33K9}7Y8LC(H%D1($F}W%6.png

  1. 当一个类收到了类加载请求,它首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一层都如此,一直递归到顶层,只有当父类加载器无法完成这个请求时,子类才会尝试加载。
  2. 加载位于rt.jar包中的java.lang.Object

8. PC寄存器

  1. 线程私有,保证线程的顺序

9. 方法区

  1. 方法区(Method area)是被所有线程共享,所有定义的方法的信息都保存在该区域,此区域属于共享区间;
  2. 如:static修饰的静态变量、final修饰的常量、class类信息(构造方法、接口定义)、运行时的常量池存在方法区中.

10. 栈

  1. 栈: 存储8种基本数据类型,对象引用,实例化的方法等. 它是先进后出、后进先出. main方法会先进入,最后出来. 线程结束,栈的生命周期就结束了.
  2. 栈+堆+方法区之间的关系
  3. 又称方法栈,线程私有的,线程执行方法是都会创建一个栈阵,用来存储局部变量表,操作栈,动态链接,方法 出口等信息.调用方法时执行入栈,方法返回式执行出栈.

11. 本地方法栈

  1. 与栈类似,也是用来保存执行方法的信息.执行Java方法是使用栈,执行Native方法时使用本地方法栈.

12. 堆

image.png

  1. 是被线程共享的一块内存区域, 创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。
  2. 由于现代 VM 采用分代收集算法, 因此 Java 堆从 GC 的角度还可以细分为:
  3. 新生代(Eden 区、 From 幸存者区和 To 幸存者区)
  4. 老年代
  5. 永久区: jdk1.8以后,叫元空间,它使用的是直接内存,与新生代和老年代分开。这个区域是常驻内存的,用来存放jdk自身携带的class对象。

13. 解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。

  1. 栈的使用:
  2. 通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间。
  3. 堆的使用:
  4. 通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域。
  5. 方法区的使用:
  6. 方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量如直接书写的100"hello"和常量都是放在常量池中,常量池是方法区的一部分。

14. 堆和栈的区别

  1. 栈是运行时单位,代表着逻辑,内含基本数据类型和堆中对象引用,所在区域连续,没有碎片;
  2. 堆是存储单位,代表着数据,可被多个栈共享(包括成员中基本数据类型、引用和引用对象),所在区域不连续,会有碎片。
  3. 1. 功能不同
  4. 栈内存用来存储局部变量和方法调用,而堆内存用来存储Java中的对象。无论是成员变量,局部变量, 还是类变量,它们指向的对象都存储在堆内存中。
  5. 2. 共享性不同
  6. 栈内存是线程私有的。
  7. 堆内存是所有线程共有的。
  8. 3. 异常错误不同
  9. 如果栈内存或者堆内存不足都会抛出异常。
  10. 栈空间不足:java.lang.StackOverFlowError。堆空间不足:java.lang.OutOfMemoryError
  11. 4. 空间大小
  12. 栈的空间大小远远小于堆的

15. 说一下 JVM由那些部分组成,运行流程是什么

image.png

  1. JVM包含两个子系统和两个组件:
  2. 两个子系统为: ClassLoader(类加载器)、Execution engine(执行引擎);
  3. 两个组件为: Runtime data area(运行时数据区)、Native Interface(本地接口)
  4. Class loader(类加载器): 根据给定的类名类加载class文件到Runtime data area中的method area.
  5. Execution engine(执行引擎): 执行classes中的指令.
  6. Native interface(本地接口): navtive libraries交互,是其他编程语言交互接口。
  7. Runtime data area(运行时数据区域): 这就是我们常说的JVM的内存.
  8. 作用: 首先通过编译器把java代码转换成字节码, 类加载器(Class loader)在把字节码加载到内存中, 将其放在运行时数据区(Runtime data area)的方法区内, 而字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统去执行, 因此需要特定的命令解析器执行引擎(Execution Engine), 将字节码翻译成底层系统指令,再交由CPU去执行, 而这个过程中需要调用其他语言的本地库接口(Native interface)来实现整个程序的功能.

16. 说一下JVM运行时数据区

  1. 程序计数器(Program Counter Register):
  2. 当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成; 为什么要线程计数器?因为线程是不具备记忆功能.
  3. Java 虚拟机栈(Java Virtual Machine Stacks):
  4. 每个方法在执行的同时都会在Java 虚拟机栈中创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
  5. 栈帧就是Java虚拟机栈中的下一个单位.
  6. 本地方法栈(Native Method Stack):
  7. 与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
  8. Native 关键字修饰的方法是看不到的,Native 方法的源码大部分都是 CC++ 的代码
  9. Java 堆(Java Heap):
  10. Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存。
  11. 方法区(Methed Area):
  12. 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

17. 描述一下JVM加载class文件的原理机制?

  1. Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。
  2. 1. 类加载器收到类加载的请求
  3. 2. 将这个请求向上委托给父类加载器去完成, 一直向上委托,直到启动类加载器
  4. 3. 启动类加载器检查是否能加载当前这个类, 能加载就结束, 使用当前的加载器,否则,抛出异常,通知子加载器进行加载.
  5. 4. 如何找不到就报错 ClassNotFound

18. Java程序运行机制详细说明

  1. 编写java源文件(.java)文件,java文件通过编译器变成了.class文件, java运行.class字节码文件时,会使用类加载器(ClassLoader)将这些.class文件加载到JVM中。将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

19. Java类加载器有哪些?

image.png

  1. 虚拟机设计团队把加载动作放到 JVM 外部实现,以便让应用程序决定如何获取所需的类, JVM 提供了 3 种类加载器:
  2. 启动类加载器(Bootstrap)
  3. 负责加载 JAVA_HOME\lib 目录中的, 或通过-Xbootclasspath 参数指定路径中的, 且被虚拟机认可(按文件名识别, rt.jar 的类。
  4. 扩展类加载器(Extension)
  5. 负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。
  6. 应用程序类加载器(Application)
  7. 负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载, 当然我们也可以通过继承 java.lang.ClassLoader实现自定义的类加载器。

20. GC是什么?为什么要有GC?

  1. GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或
  2. 者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象
  3. 是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方
  4. 法。

21. 你知道哪些JVM性能调优?

  1. 设定堆内存大小
  2. -Xmx:堆内存最大限制。
  3. 设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代
  4. -XX:NewSize:新生代大小
  5. -XX:NewRatio 新生代和老生代占比
  6. -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比
  7. 设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC

22. GC常用算法

  1. 引用计数法: 记录每个对象 的引用次数,长时间没有被引用的对象就被清除掉。
  2. 复制算法: 复制算法最佳使用场景:对象存活度较低的时候 -> 新生区
  3. 好处:没有内存碎片
  4. 坏处:浪费内存空间,多了一半to空间永远是空的。
  5. 标记清除算法: 扫描这些对象: 对活着的对象进行标记,清除没有被标记的对象
  6. 优点: 不需要额外的空间。
  7. 缺点: 两次扫描,严重浪费时间,会产生内存碎片。
  8. 标记压缩: 标记 -> 清除 -> 压缩