确定要面试问我 JVM 吗?我打算聊一个小时的!,目前最全的《Java 面试题及解析》
public?static?void?main(String[]?args)?{
List?list?=?new?ArrayList();
while?(true)?{
list.add(new?Cat());
}
}
}
18.空间什么情况下会抛出 OutOfMemoryError?
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出 OutOfMemoryError。
19.如何实现 StrackOverflowError?
public?static?void?main(String[]?args)?{
eat();
}
public?static?void?eat?()?{
eat();
}
20.如何设置直接内存容量?
通过 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆的最大值一样。
21.Java 堆内存组成?
https://user-gold-cdn.xitu.io/2020/5/13/1720da9b1f827a21?imageView2/0/w/1280/h/960/ignore-error/1
堆大小 = 新生代 + 老年代。如果是 Java8 则没有 Permanent Generation。
其中新生代(Young) 被分为 Eden 和 S0(from)和 S1(to)。
22.Edem : from : to 默认比例是?
Edem : from : to = 8 : 1 : 1
此比例可以通过 –XX:SurvivorRatio 来设定
23.垃圾标记阶段?
在 GC 执行垃圾回收之前,为了区分对象存活与否,当对象被标记为死亡时,GC 才回执行垃圾回收,这个过程就是垃圾标记阶段。
24.引用计数法?
比如对象 a,只要任何一个对象引用了 a,则 a 的引用计数器就加 1,当引用失效时,引用计数器就减 1,当计数器为 0 时,就可以对其回收。
但是无法解决循环引用的问题。
25.根搜索算法?
跟搜索算法是以跟为起始点,
按照从上到下的方式搜索被根对象集合所连接的目标对象是否可达(使用根搜索算法后,内存中 的存活对象都会被根对象集合直接或间接连接着),如果目标对象不可达,就意味着该对象己经死亡,便可以在 instanceOopDesc 的 Mark World 中将其标记为垃圾对象。
在根搜索算法中, 只有能够被根对象集合直接或者间接连接的对象才是存活对象。
26.JVM 中三种常见的垃圾收集算法?
标记-清除算法(Mark_Sweep)
复制算法(Copying)
标记-压缩算法(Mark-Compact)
27.标记-清除算法?
首先标记出所有需要回收的对象,在标记完成后统一回收掉所有的被标记对象。
https://user-gold-cdn.xitu.io/2020/5/13/1720da9b1f96fa42?imageView2/0/w/1280/h/960/ignore-error/1
缺点:
标记和清除的效率都不高。
空间问题,清除后产生大量不连续的内存随便。如果有大对象会出现空间不够的现象从而不得不提前触发另一次垃圾收集动作。
28.复制算法?
他将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。https://user-gold-cdn.xitu.io/2020/5/13/1720da9b212095d3?imageView2/0/w/1280/h/960/ignore-error/1
优点:
解决了内存碎片问题。
缺点:
将原来的内存缩小为原来的一半,存活对象越多效率越低。
29.标记-整理算法?
先标记出要被回收的对象,然后让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。解决了复制算法和标记清理算法的问题。
https://user-gold-cdn.xitu.io/2020/5/13/1720da9b4fb309b4?imageView2/0/w/1280/h/960/ignore-error/1
30.分代收集算法?
当前商业虚拟机的垃圾收集都采用“分代手机算法”,其实就根据对象存活周期的不同将内存划分为几块,一般是新老年代。根据各个年代的特点采用最适当的收集算法。
31.垃圾收集器?
如果说垃圾收集算法是方法论,那么垃圾收集器就是具体实现。连线代表可以搭配使用。
32.Stop The World?
进行垃圾收集时,必须暂停其他所有工作线程,Sun 将这种事情叫做"Stop The World"。
33.Serial 收集器?
单线程收集器,单线程的含义在于它会 stop the world。垃圾回收时需要 stop the world ,直到它收集结束。所以这种收集器体验比较差。
34.PartNew 收集器?
Serial 收集器的多线程版本,除了使用采用并行收回的方式回收内存外,其他行为几乎和 Serial 没区别。
可以通过选项“-XX:+UseParNewGC”手动指定使用 ParNew 收集器执行内存回收任务。
36.Parallel Scavenge?
是一个新生代收集器,也是复制算法的收集器,同时也是多线程并行收集器,与 PartNew 不同是,它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码 的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)), 高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。
他可以通过 2 个参数精确的控制吞吐量,更高效的利用 cpu。
分别是: -XX:MaxGcPauseMillis 和 -XX:GCTimeRatio
37.Parallel Old 收集器?
Parallel Scavenge 收集器的老年代版本,使用多线程和标记-整理算法。JDK 1.6 中才开始提供。
38.CMS 收集器?
Concurrent Mar Sweep 收集器是一种以获取最短回收停顿时间为目标的收集器。重视服务的响应速度,希望系统停顿时间最短。采用标记-清除的算法来进行垃圾回收。
39.CMS 垃圾回收的步骤?
初始标记 (stop the world)
并发标记
重新标记 (stop the world)
并发清除
初始标记仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快。
并发标记就是进行 Gc Roots Tracing 的过程。
重新标记则是为了修正并发标记期间,因用户程序继续运行而导致的标记产生变动的那一部分对象的标记记录,这个阶段停顿时间一般比初始标记时间长,但是远比并发标记时间短。
整个过程中并发标记时间最长,但此时可以和用户线程一起工作。
41.CMS 收集器优点?缺点?
优点:
并发收集、低停顿
缺点:
对 cpu 资源非常敏感。
无法处理浮动垃圾。
内存碎片问题。
42.G1 收集器?
Garbage First 收集器是当前收集器技术发展的最前沿成果。jdk 1.6_update14 中提供了 g1 收集器。
G1 收集器是基于标记-整理算法的收集器,它避免了内存碎片的问题。
可以非常精确控制停顿时间,既能让使用者明确指定一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不多超过 N 毫秒,这几乎已经是实时 java(rtsj)的垃圾收集器特征了。
42. G1 收集器是如何改进收集方式的?
极力避免全区域垃圾收集,之前的收集器进行收集的范围都是整个新生代或者老年代。而 g1 将整个 Java 堆(包括新生代、老年代)划分为多个大小固定的独立区域,并且跟踪这些区域垃圾堆积程度,维护一个优先级李彪,每次根据允许的收集时间,优先回收垃圾最多的区域。从而获得更高的效率。
43.虚拟机进程状况工具?
jps (Jvm process status tool ),他的功能与 ps 类似。
可以列出正在运行的虚拟机进程,并显示执行主类(Main Class,main()函数所在的类)的名称,以及浙西进程的本地虚拟机的唯一 ID。
语法 :jps [options] [hostid]
-q 主输出 lvmid,省略主类的名称
-m 输出虚拟机进程启动时传递给主类 main()函数的参数
-l ? ?输出主类全名,如果进程执行是 Jar 包,输出 Jar 路径
-v 输出虚拟机进程启动时 JVM 参数
44.虚拟机统计信息工具?
jstat(JVM Statistics Montoring Tool)是用于监视虚拟机各种运行状态信息命令行工机具。他可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、jit 编译等运行数据。
jstat [option vmid [interval[s|ms] [count]] ]
interval 查询间隔
count 查询次数
如果不用这两个参数,就默认查询一次。
option 代表用户希望查询的虚拟机信息,主要分 3 类:
类装载
垃圾收集
运行期编译状况
45.jstat 工具主要选项?
-class ? ?监视类装载、卸载数量、总空间及类装载锁消耗的时间
-gc ? ? ? ? 监视 Java 堆状况,包括 Eden 区,2 个 survivor 区、老年代
-gccapacity 监视内容与-gc 基本相同,但输出主要关注 Java 堆各个区域使用的最大和最小空间
-gcutil ?监视内容与-gc 基本相同,主要关注已经使用空间站空间百分比
-gccause 与-gcutil 功能一样,但是会额外输出导致上一次 GC 产生的原因
-gcnew ?监视新生代的 GC 的状况
-gcnewcapacity 监视内容与 -gcnew 基本相同,输出主要关注使用到的最大最小空间
-gcold ?监视老年代的 GC 情况
-gcoldcapacity ?监控内容与 -gcold 基本相同,主要关注使用到的最大最小空间
-compiler 输出 jit 编译器编译过的方法、耗时等信息
45.配置信息工具?
jinfo(Configuration Info for Java)的作用是实时地查看和调整虚拟机的各项参数。
使用 jps 命令的 -v 参数可以查看虚拟机启动时显示指定的参数列表。
jinfo 语法: jinfo [option] pid
46.内存映像工具?
jmap(Memory Map for Java) 命令用于生成堆转储快照(一般称为 heapdump 或 dump 文件)。
语法 :jmap [option] vmid
它还可以查询 finalize 执行队列,Java 堆和永久代的详细信息,如果空间使用率、当前用的是哪种收集器等。
-dump 生成 Java 堆转储快照,其中 live 自参数说明是否只 dump 出存活对象
-finalizerinfo 显示在 F -Queue 中等待 Finalizer 线程执行 finalize 方法的对象。只在 Linux/Solaris 平台下有效
-heap 显示 Java 堆详细信息,如使用哪种回收器、参数配置、分代状况。
-histo 显示堆中对象统计信息、包括类、实例数量和合计容量。
-F 当虚拟机进程对-dump 选项没有响应时,可使用这个选项强制生成 dump 快照。
47.虚拟机堆转存储快照分析工具?
jhat ( JVM Heap Analysis Tool) 用来分析 jmap 生成的堆转储快照。
48.堆栈跟踪工具?
jstack(Stack Trace for Java) 命令用于生成虚拟机当前时刻的线程快照(一般称为 thread dump 或 javacore 文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因。
jstack [option] vmid
-F ?当正常输出的请求不被响应时,强制输出线程堆栈
-l ?除堆栈外,显示关于锁的附加信息
-m 如果调用本地方法的花,可以显示 C/C++ 的堆栈
49.除了命令行,还有什么可视化工具?
JConsole 和 VisualVM,这两个工具是 JDK 的正式成员。
50.类的生命周期?
image
51.类加载过程?
加载 -> 校验 -> 准备 -> 解析 -> 初始化
52.链接阶段分几个步骤?
校验 -> 准备 -> 解析
53.哪 5 种情况必须对类进行初始化?
1.遇到 new、getstatic、putstatic、invokestatic 4 个字节码指令时。
2.使用 java.lang.relect 包的方法对类进行反射调用时。
3.当初始化一个类的时候,如果父类没被初始化,则先初始化父类。
4.当虚拟机启动时,指定了执行主类(main()的方法的那个类),则需要先初始化这个主类。
5.JDK1.7 动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后解析结果 REF_getStatic,REF_putStatic,REF_invokeStatic 的方法句柄,且该句柄对应的类没有初始化,则需要先初始化这个类。
54.以下代码会输出?
public?class?TestStatic?{
public?static?void?main(String[]?args)?{
System.out.println(SubClass.value);
}
}
class?SuperClass?{
static?{
System.out.println("Java 小咖秀?super?init");
评论