JVM
文章目录
- JVM
- 1、什么是JVM?它是做什么的?
- 2、JVM的组成部分有哪些?
- 3、什么是字节码?为什么Java使用字节码?
- 4、什么是即时编译器(Just-In-Time Compiler)?它与解释器有什么区别?
- 5、JVM内存分为哪些区域?请描述它们的作用和特点。
- 6、堆的详解,新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
- 7、Java对象在内存中是如何分配的?请解释堆和栈的区别。
- 8、什么是垃圾回收(Garbage Collection)?为什么需要进行垃圾回收?
- 9、垃圾回收器有哪些类型?请描述它们的工作原理和适用场景。
- 10、如何判断对象是否可以被垃圾回收?
- 11、什么是类加载器(ClassLoader)?它的作用是什么?请解释双亲委派模型。
- 12、类加载的过程是怎样的?请解释加载、验证、准备、解析和初始化这五个阶段的含义。
- 13、什么是永久代(Permanent Generation)和元数据区(Metaspace)?它们的作用是什么?
- 14、Java中的String为什么被设计为不可变类?有什么好处?
- 15、如何进行JVM性能调优?请列举一些常见的优化技巧和工具。
- 16、详细介绍一下 CMS 垃圾回收器?
- 17、简述分代垃圾回收器是怎么工作的?
1、什么是JVM?它是做什么的?
JVM是Java虚拟机的缩写。主要是将Java字节码解释或编译为机器码,可在不同操作系统和硬件平台运行Java程序。一次编写,到处运行。
JVM有以下主要任务:
-
类加载:将子字节码加载到内存中,将其转化为可执行的类。
-
字节码执行:编译字节码。
-
内存管理:JVM管理程序的内存分配和释放。
-
垃圾回收:检测和回收不再使用的对象,释放内存空间。
-
安全管理:提供安全机制,确保Java在受控环境运行,防止恶意代码执行。
-
线程 管理:允许多线程执行。提供线程同步和协作的机制。
-
异常处理:可捕获和处理Java中异常。
2、JVM的组成部分有哪些?
①类加载器:将字节码文件加载到JVM中,并将其转换为可执行的类。
②运行时数据区:jvm将内存划分为不同数据区域,存储程序运行时的数据。主要包含方法区:存储类结构信息,静态变量,常量池。
堆:存储对象实例和数组。
java栈:每个线程运行时都会创建一个栈,存储局部变量,方法参数等。
本地方法栈:执行本地方法所用。
程序计数器:指示当前线程正在执行的指令地址。
③执行引擎:解释和执行字节码。
④垃圾回收器:自动管理内存,回收不再使用的对象。
⑤本地方法接口:允许Java程序调用本地方法库中的方法。
⑥可拓展性:JVM提供了一系列工具和接口,用于诊断和监控应用程序的性能、调试代码和进行性能优化。
3、什么是字节码?为什么Java使用字节码?
字节码是Java编译器将Jaava代码编生成的中间代码。
使用字节码主要原因:
- 平台无关性
- 安全性:字节码执行之前JVM会进行安全检查。
- 性能优化:字节码被即时编译器动态编译为本地机器码,提高效率。
- 可以执行:不依赖特定平台。
- 开发效率:编译更快。
4、什么是即时编译器(Just-In-Time Compiler)?它与解释器有什么区别?
即时编译器是将字节码动态编译成本地机器码,提高程序执行效率。
和解释器的区别如下:
①执行方式:解释器是逐条解释执行字节码,即时编译器是在运行时将频繁执行的代码编译为本地机器码,直接执行编译后的机器码。
②执行效率:解释器每次执行都要解释字节码执行,慢;
即时编译器将热点代码编译后直接执行机器码,快。
③优化能力:解释器每次执行都会解释,没有优化机会。
即时编译器可以动态对热点代码优化,提高效率。
④编译延迟:解释器可以立即执行,不需要等待编译。
即时编译器在运行时编译热点代码,刚启动存在延迟。
⑤内存占用:解释器占用内存较少。
即时编译器在编译过程中会生成本地机器码,需要更多空间。
5、JVM内存分为哪些区域?请描述它们的作用和特点。
- 程序计数器:指示当前线程正在执行的字节码指令的地址。
- Java虚拟机栈:存储线程的方法和局部变量等信息。
- 本地方法栈:存储本地方法,局部变量等信息。
- 堆:存储对象实例和数组。分为新生代和老年代。新生代又分为伊甸区和Survivor区。
- 方法区:存储一家在的类的信息、常量、变量等。
- 运行时常量池:存储编译器生成的各种字面量和符号引用。
6、堆的详解,新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
用于存储对象实例和数组。划分为新生代和老年代。
新生代:
- Eden区:对象被创建时首先分配在Eden区。Eden区满时,出发Young GC进行垃圾回收。幸存对象会被移动到Survivor区。
- Survivor区:分为From区和To区。Minor GC发生时,幸村对象从Eden区和From区复制到To区,复制过程中对象年龄逐渐增加,多次幸存后,会一共到老年区。
老年代:
分为
CMS收集器:采用并发标记和并发清除方式进行垃圾回收。
G1收集器:采用分代收集和并发标记清除方式,将堆划分为多个区域,处理。
Serial Old收集器:采用单线程进行垃圾回收。
存储多次经过Minor GC后仍然存活的对象。新生代经历多次幸存后,会晋升到老年代。老年代的垃圾回收频率更低,对象存活 更稳定。老年代满时,会触发Full GC进行垃圾回收。
区别
新生代
主要负责回收新创建的对象,一般采用复制算法。分区,
将内存分为Eden区、Survivor区From和Survivor区To。通过将存活的对象复制到Survivor区,
然后清空Eden区和From区的方式来回收垃圾。
老年代
主要回收存活时间长的对象,一般采用标记清除算法,
老生代垃圾回收器通常需要在停顿的情况下进行垃圾回收,可能会导致较长的停顿时间
7、Java对象在内存中是如何分配的?请解释堆和栈的区别。
对象实例存储在堆中,堆是动态分配的内存区域。
Java中的方法和局部变量存储在栈(stack)中。栈是一种具有后进先出(LIFO)特性的数据结构。
堆的分配和释放相对较慢,
栈的分配和释放速度非常快,但是栈的大小是有限的。当方法调用嵌套层级过深或者局部变量过多时,栈可能会溢出,导致栈溢出错误。
1、存储内容:堆存储对象实例和数组,栈存储方法调用和局部变量。
2、线程共享:堆被所有线程共享。每个线程都有自己的栈。
3、内存管理:堆是动态分配,由垃圾回收器分配和销毁。栈是自动的,随着方法的调用和返回自动分配释放。
4、内存大小:堆是可以通过jvm配置,栈 固定。
5、异常:堆空间不足导致OutOfMemmoryErrror,栈内存不足导致StackOverFlowError。
8、什么是垃圾回收(Garbage Collection)?为什么需要进行垃圾回收?
垃圾回收用于检测和回收程序中不再使用的资源,
需要进行垃圾回收的原因:
- 防止内存泄漏:对象或者数据不再使用,如果不回收,会一直占用内存空间。
- 动态内存管理:动态创建对象,减少手动释放。
- 提高性能:根据程序的运行情况智能地管理内存,减少内存碎片化的问题。
9、垃圾回收器有哪些类型?请描述它们的工作原理和适用场景。
- 标记-清除:分为标记阶段和清除阶段,
- 复制:分为活动区域,和回收区域,活动区满了的情况下将存活的对象复制到回收区,清除活动区所有对象。
- 标记-压缩:它首先通过标记阶段标记可达对象,然后将存活对象紧凑地移动到内存的一端,清除边界之外的内存空间。
- 分代:新生代、老年代。
10、如何判断对象是否可以被垃圾回收?
1、可达性分析算法:垃圾回收器自动判断。Java中的垃圾回收器使用可达性分析算法判断对象是否可以被回收。
如果对象不再被任何活动的引用链所引用,那就是不可达,可以被回收。
2、引用计数法:每个对象都有一个引用计数器,当有引用指向该对象时,计数器加1,当引用失效时,计数器减1。
当计数器为0时,表示该对象不再被引用,可以被回收。
3、引用队列: 将某些对象的引用放入队列中。当这些对象变为不可达时,它们会被添加到引用队列中,
开发人员可以在合适的时机、处理这些对象。
11、什么是类加载器(ClassLoader)?它的作用是什么?请解释双亲委派模型。
类加载器负责将Java类的字节码加载到内存中,将其转化为可执行的java对象。
双亲委派模型是类加载器的一种,当一个类加载器需要加载某个类时,它首先将任务委托给父类加载器。如果父类加载器无法加载该类,子类加载器才会尝试加载。
双亲委派模型优点:
1、避免类重复加载:先检查父类有没有祖先加载过,避免重复加载同一个类。
2、安全性
3、类的隔离性:不同类加载器加载位于不同命名空间的类,相同类名的类可以被不同的类加载器加载。
12、类加载的过程是怎样的?请解释加载、验证、准备、解析和初始化这五个阶段的含义。
-
加载:将类的字节码文件加载到jvm。
-
验证:确保加载的字节码文件是否符合规范。
-
准备:为类的静态便令在内存中分配空间,设置初始值。
-
解析: 将符号引用转为直接引用。
-
初始化: 按顺序执行静态变量的初始化和静态代码块中的代码。
13、什么是永久代(Permanent Generation)和元数据区(Metaspace)?它们的作用是什么?
永久代:用于存储类的相关信息,如类的结构信息,运行时常量池,静态便令,即时编译器编译后的代码等。
永久代的大小是有限的,
元数据区主要是存储类的元数据信息,可以动态加载类,大小可以通过jvm参数进行配置,可以自动拓展。
14、Java中的String为什么被设计为不可变类?有什么好处?
1、字符串池的优化:String是不可变的,所以相同内容的字符串在内存中只需要存储一份。创建新对象时,jvm首先检查池中是否存在相同内容的,如果存在,直接返回引用。可节省空间,提高性能。
2、线程安全:值不可变。多个线程可以共享同一个String对象。
3、缓存哈希值:String类在创建时会计算并缓存它的哈希值。之后再次需要哈希值时可以直接使用缓存的值,提高了性能。
4、安全性。
5、方法和参数传递:String不可变,更安全。
15、如何进行JVM性能调优?请列举一些常见的优化技巧和工具。
1、内存管理:通过-Xmx和-Xms调整堆的最大和初始化大小。
2、线程管理:减少线程数量,避免创建过多线程。选择合适的线程池。
3、代码优化:减少对象创建。减少堆共享资源的锁竞争。
4、JVM参数调优。调整堆和栈大小:通过-Xmx、-Xms和-Xss参数调整堆和栈的大小,以满足应用程序的需求。
16、详细介绍一下 CMS 垃圾回收器?
CMS采用了并发标记-清除算法。
回收流程:
- 初始标记:标记所有对象。这个阶段是暂停应用程序的阶段。
- 并发标记阶段:应用程序继续运行,垃圾收集器与应用程序并发执行。垃圾收集器通过遍历堆中的对象,
标记出所有可达对象。 - 重新标记阶段:并发标记结束,在此暂停应用程序重新标记,标记在并发阶段发生变化的对象。
- 并发清除阶段:重新标记之后,垃圾收集器并发运行,进行清除操作。释放未被引用的对象占用的内存空间。
17、简述分代垃圾回收器是怎么工作的?
分代垃圾回收器通过根据对象的生命周期将堆内存划分为不同的代,
并根据每个代的特性采取不同的垃圾回收策略,以提高垃圾回收的效率和性能。