面试题,Java虚拟机(JVM)篇

本文详细介绍了JVM的主要组成部分,包括类装载器、执行引擎、运行时数据区和本地接口,以及JVM内存模型的划分,新生代、老年代和持久代的区别。还探讨了Java对象的创建方式、引用类型和不同垃圾回收算法。
摘要由CSDN通过智能技术生成

1、JVM 的主要组成部分及其作用

1.1、JVM包含两个子系统和两个组件

两个子系统为Class loader(类装载)、Execution engine(执行引擎);

两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。

  • 类装载:根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area。

  • 执行引擎:执行classes中的指令。

  • 本地接口:与native libraries交互,是其它编程语言交互的接口。

  • 运行时数据区域:这就是我们常说的JVM的内存。

1.2、JVM 的主要组成部分的作用

        首先通过编译器把 Java 代码转换成字节码,类加载器(ClassLoader)再把字节码加载到内存中,将其放在运行时数据区(Runtime data area)的方法区内,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

2、JVM内存模型划分

Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有些区域随着虚拟机进程的启动而存在,有些区域则是依赖线程的启动和结束而建立和销毁。Java 虚拟机所管理的内存被划分为如下几个区域:

程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;
方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

3、JAVA堆栈的区别

物理地址

堆的物理地址分配对对象是不连续的。因此性能慢些。在GC的时候也要考虑到不连续的分配,所以有各种算法。比如,标记-消除,复制,标记-压缩,分代(即新生代使用复制算法,老年代使用标记——压缩)

栈使用的是数据结构中的栈,先进后出的原则,物理地址分配是连续的。所以性能快。

内存分别

堆因为是不连续的,所以分配的内存是在运行期确认的,因此大小不固定。一般堆大小远远大于栈。

栈是连续的,所以分配的内存大小要在编译期就确认,大小是固定的。

存放的内容

堆存放的是对象的实例和数组。因此该区更关注的是数据的存储

栈存放:局部变量,操作数栈,返回结果。该区更关注的是程序方法的执行。

PS

静态变量放在方法区。
静态的对象还是放在堆。
程序的可见度

堆对于整个应用程序都是共享、可见的。

栈只对于线程是可见的。所以也是线程私有。他的生命周期和线程相同。

4、描述新生代、老年代、持久代区别

新生代:所有新生成的对象首先都是放在新生代的,新生代的目标就是尽可能快速的收集掉那些生命周期短 的对象。

老年代:在新生代中经历了多次垃圾回收后仍然存活的对象会被放到老年代中,存放的是一些生命周期较长的对象。

持久代:用于存放静态文件,如今Java类、方法等。

5、如何判断一个对象/常量应该被回收?

引用计数法:给对象增加一个计数器,当引用它时,计数器就加一,当引用失效时,计数器就减一;JVM由于循环引用会导致引用计数法失效而并没有采用这种方式来判断对象是否应该被回收。

可达性分析法:通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的 路径称之为"引用链",当一个对象到GC Roots没有任何的引用链相连时,证明此对象应该被回收。

5.1、描述类的生命周期

        一个Java类从开始到结束整个生命周期会经历7个阶段:加载、验证、准备、解析、初始化、使用和卸载。其中验证、准备、解析三个部分又统称为连接。

5.2、简述Java垃圾回收机制

        在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

6、JVM调优(知道哪些工具)

说一下 JVM 调优的工具?
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。

jconsole:用于对 JVM 中的内存、线程和类等进行监控;
jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

7、JVM调优相关参数

-Xms2g:初始化推大小为 2g;
-Xmx2g:堆最大内存为 2g;
-XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
-XX:+PrintGC:开启打印 gc 信息;
-XX:+PrintGCDetails:打印 gc 详细信息。

8、描述双亲委派模式

        在介绍双亲委派模型之前先说下类加载器。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立在 JVM 中的唯一性,每一个类加载器,都有一个独立的类名称空间。类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转化为 class 对象。

        双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。

        当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

9、描述深克隆和浅克隆区别

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。

浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。

10、JAVA对象的创建方式有哪些

Header解释
使用new关键字调用了构造函数
使用Class的newInstance方法调用了构造函数
使用Constructor类的newInstance方法调用了构造函数
使用clone方法没有调用构造函数
使用反序列化没有调用构造函数

11、描述强引用、软引用、弱引用、虚引用区别

强引用:发生 gc 的时候不会被回收强引用:发生 gc 的时候不会被回收。

软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。

弱引用:有用但不是必须的对象,在下一次GC时会被回收。

虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

12、JVM有哪些垃圾回收算法

标记-清除算法标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。

复制算法按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。

标记-整理算法标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。

分代算法根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值