前言

这是一篇看了能说的进去的jvm面试;集体能力无限,文中形容不免有谬误,请斧正;

一 JVM面试

1.1 简述Java内存模型(重点)

jvm会将运行程序所治理的空间分为若干局部,每个局部都起到至关重要的局部;jdk1.8java运行时数据区如下:

程序计数器:以后线程执行字节码的行号指示器;字节码解析器通过扭转计数器的值,来选取下一条须要执行的字节码指令,分支、循环、跳转、异样解决、线程复原等根底性能;

Java 虚拟机栈: java办法执行的内存模型,每个办法被执行的时候都会创立帧栈用于存储局部变量表、操作数栈、动静链接、办法进口等信息;

本地办法栈: 执行java的native办法服务,每个办法被执行的时候都会创立帧栈用于存储局部变量表、操作数栈、动静链接、办法进口等信息;

Java 堆: 贮存对象的实例和数组;

办法区: 非堆,贮存类的构造信息;例如运行时常量池的字段和办法数据,构造函数和一般办法的字节码内容等;

科普运行时罕用池:运行时罕用池是class文件中每一个类或者接口的常量池表的运行表现形式,包含若干种常量,如字段和办法的援用;在类加载至虚拟机的时候就会创立运行时常量池;

科普帧栈:帧栈用于贮存数据和局部过程后果的数据,同时也会解决动静链接,办法返回值和分派;帧栈随着办法的创立而创立,随着办法的销毁而销毁;帧栈中保护着本地变量表,操作数栈,和指向以后办法所属类的运行常量池的援用;

留神:jdk1.8曾经应用元空间代替了jdk1.7办法区中的永恒代,元空间存在于native内存中,其大小依据本地内存而定,没有限度;具体看官网地址

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html#sthref66

1.2 简述类的加载过程(重点)

类的加载过程分为 加载,链接,初始化,应用,和卸载5个阶段,其中连贯阶段又分为验证 筹备和解析阶段;

  1. 加载阶段:次要是取得类的二进制字节流在内存中生产Class对象;
  2. 连贯阶段:验证Class的安全性,合乎虚拟机标准;筹备类的内存调配和初始化变量;解析常量池的符号援用(将符号援用转换为间接援用);
  3. 初始化阶段:对动态变量和动态代码赋初值;
  4. 应用阶段;
  5. 卸载阶段;

1.3 哪些地方会产生OOM?

内存溢出:申请了8个字节的空间,然而你在这个空间写入9或以上字节的数据,呈现内存溢出;

在java内存模型中只有程序计数器不会产生OOM(out of memory),其余地区都会产生OOM;

1.4 什么是双亲委派模型?

当一个类收到了类加载申请时,本人不会先去加载这个类,而是将其委派给父类去加载,如果父类不能加载,反馈给子类,由子类去实现类的加载;

这边有可能会问,你都晓得哪些类加载器

  1. 启动类加载器:次要加载%JAVA_HOME%\lib 目录下的类库文件或者 -Xbootclasspath 所指定的类库文件(加载外围类)
  2. 扩大类加载器:次要加载%JAVA_HOME%\lib\ext目录下的类库文件或者java.ext.dirs零碎变量所指定的类库文件(加载扩大库)
  3. 程序利用类加载器:次要加载用户类门路(classpath)所指定的类库。
  4. 用户自定义类加载器:加载用户自定义的类库。

如何突破双亲委派模型

双亲委派模型都依附loadClass(),重写loaderClass()即可;

1.5 新生代中辨别Eden和Survivor的作用是什么

新生代分为 3 个分区:Eden(伊甸园)、Survivor1、Survivor2;其中Survivor1、 Survivor2 合起来成为Survivor(幸存区); 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象都会被送到老年代。老年代将很快被填满,老年代每产生一次Full GC 的速度比 Minor GC慢10倍;

Survivor 的作用就是缩小老年代Full GC 的次数,相当于缓冲带;

Eden和Survivor的比例调配8:1;

1.6简述分代垃圾回收器工作流程

  1. 泛滥的对象都调配在Eden;
  2. 一个survivor空间接管来自Eden存活的对象;
  3. 2 个survivor 空间的对象会互相复制,不论survivor 空间的对象如何复制,总有一个survivor 空间是空的用于接管来自Eden存活的对象;
  4. 当survivor 空间有余时,对象就会复制到老年代;

官网:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/generations.html#sthref16

1.7 简述内存调配与回收策略(重点)

  • 大多数状况下对象都优先间接调配在Eden ,当Eden 空间有余时会产生Minor GC, 每通过一次Minor GC,年龄+1,若年龄超过15,则被进入到老年态。当老年代空间有余时就会产生 Full GC;
  • 长期存活对象将进入老年代
  • 如果是大对象(须要大量间断内存空间的对象)间接进入老年代 ;
会呈现的小问题就是:Minor GC和Full GC触发条件,答默认状况下产生15次Minor GC之后就会触发一次Full GC

1.8 GC是什么? 为什么要有 GC?

GC 是垃圾收集(GabageCollection);Java 提供的 GC 性能能够主动监测对象是否超过作用域从而达到主动回收内存的目标,而不须要人为手动开释内存;次要调用的是 System.gc() 和 Runtime.getRuntime().gc();

1.9 简述CMS收集器

CMS(Concurrent Mark Sweep)收集器基于标记—革除算法实现的收集器,是一种以获取最短回收进展工夫为指标的收集器。次要长处是并发收集,低进展,在cpu多核的状况下性能较好。在启动 JVM 的参数加上

“-XX:+UseConcMarkSweepGC”来指定应用 CMS 垃圾回收器;其应用在老年代 能够配合新生代的Serial和ParNew收集器一起应用;因为 CMS 应用 标记—革除算法 GC时会产生大量碎片,有可能提前触发Full GC;如果在老年代充斥之前无奈回收不可达对象,或者没有足够的空间满足调配就会导致Concurrent Mode Failure(并发模式故障);

官网:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html

2.0 简述G1收集器

G1(Garbage-First)从整体来看是基于标记—整顿算法实现的收集器,可能实现并发并行,对cpu利用率较高,缩小进展工夫。指标是取代jdk1.5公布的CMS收集器。G1收集器收集范畴是老年代和新生代,不须要联合其余收集器应用,G1收集器可预测垃圾回收的进展工夫,对空间进行整合;因为G1是基于复制算法实现,当没有足够的空间(region)调配存活的对象就会导致Allocation (Evacuation) Failure(调配失败)

官网:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc.html#garbage_first_garbage_collection

2.1 jvm调优时如何抉择垃圾回收器(重点)

  • 当利用的数据集较小时,约100M时或者 单线程利用,没有严格的进展要求抉择serial 收集器; 参数选项:-XX:+UseSerialGC;
  • 如果对利用的性能要求高或者没有进展要求,能够承受1秒或者更久的进展抉择parallel收集器; 参数选项:XX:+UseParallelGC;
  • 如果对响应工夫有很高的要求相比于吞吐量,谋求更小的进展工夫能够应用CMS或者G1; 参数选项:-XX:+UseConcMarkSweepGC 或者 XX:+UseG1GC

官网:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html#sthref27

2.2 简述GC中Stop the world(重点)

Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其余所有线程都被挂起。Stop-The-World对系统性能存在影响,因而垃圾回收的一个准则是尽量减少“Stop-The-World”的工夫;

2.3 垃圾回收算法(重点)

标记-革除法:标记出没有用的对象,之后一个一个回收掉

  • 毛病:标记和革除两个过程效率不高,产生内存碎片导致须要调配较大对象时无奈找到足够的间断内存而须要触发一次GC操作;
  • 长处:实现简略;

复制算法: 依照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,而后再把已应用的内存空间一次清理掉

  • 毛病:将内存放大为原来的一半;
  • 长处:按程序分配内存,实现简略、运行高效,不必思考内存碎片。

标记-整顿法:标记出没有用的对象,让所有存活的对象都向一端挪动,而后间接革除掉端边界以外的对象

  • 长处:解决了标记- 革除算法导致的内存碎片问题。
  • 毛病:仍须要进行部分对象挪动,肯定水平上升高了效率。

分代回收:依据对象存活周期的不同将内存划分为几块,个别是新生代和老年代,新生代根本采纳复制算法,老年代采纳标记整顿算法

2.4 你晓得哪些垃圾收集器

2.5 你有遇到过java内存透露么?(次重点)

内存透露:new申请了一块内存,起初很长时间都不再应用了(按理应该开释),然而因为始终被某个或某些实例所持有导致 GC 不能回收;

经典案例

void test(){
Vector vector = new Vector();
for (int i = 1; i<100; i++)
{
Object object = new Object();
vector.add(object);
object = null;
}
//...对vector的操作
//...与vector无关的其余操作
}

手动解决赋值null即可

void test(){
Vector vector = new Vector();
for (int i = 1; i<100; i++)
{
Object object = new Object();
vector.add(object);
object = null;
}
//...对vector的操作
vector = null;
//...与vector无关的其余操作
}

还有各种流和socket的close办法未被调用也会产生内存透露问题;

2.6 对象什么时候会被GC

  • 援用计数器法:为每个对象创立一个援用计数,有对象援用时计数器 +1,援用被开释时计数 -1,当计数器为 0 时就能够被回收。它有一个毛病不能解决循环援用(A->B,B->A)的问题,那么 AB 将永远不会被回收;
  • 可达性剖析算法:从 GC Roots 开始向下搜寻,搜寻所走过的门路称为援用链。当一个对象到 GC Roots 没有任何援用链相连时,则证实此对象是能够被回收的。

2.7 说下Java内存堆和栈区别(偶然会问到)

  • 栈内存用来存储根本类型的变量和对象的援用变量,堆内存用来存储Java中的对象;
  • 栈内存线程公有,堆内存线程共享
  • 栈内存不足时,JVM会抛出java.lang.StackOverFlowError(个别产生在递归的时候);堆内存不足时,JVM会抛出java.lang.OutOfMemoryError
  • 栈的内存远小于堆内存,-Xss选项设置栈的大小。-Xms选项能够设置堆的开始大小;

2.8 强援用、软援用、弱援用、虚援用以及他们之间和gc的关系

  • 强援用:new出的对象之类的援用, 只有强援用还在,gc时永远不会被回收
  • 软援用:有用但非必须的对象,内存溢出异样之前,回收
  • 弱援用:有用但非必须的对象,对象能生存到下一次垃圾收集产生之前。
  • 虚援用:对生存工夫无影响,在垃圾回收时失去告诉。

2.9java对象创立

  • 应用new关键字创建对象; 会调用构造方法;
  • 应用Class类的newInstance办法(反射机制);会调用构造方法;
  • 应用Constructor类的newInstance办法(反射机制);会调用构造方法;
  • 应用Clone办法创建对象;不会调用构造方法;
  • 应用(反)序列化机制创建对象;不会调用构造方法;

3.0 如果对象的援用被置为 null,垃圾收集器是否会立刻回收对象?

不会,在下一个垃圾回收周期中回收对象。

3.1 jvm调优工具又哪些?各自的作用又是什么(重点)

  • jps: 查看过程的参数信息;
  • jstat: 查看某个Java过程内的线程堆栈信息;
  • jinfo: 查看虚拟机参数;
  • jmap:查看堆内存应用情况,生成快照存储(dump文件);
  • jhat: 剖析jmap dump生成的快照文件;
  • jconsole: 基于JMX的可视化工具,监控 cpu, 内存,线程等应用状况;
  • jvisualvm: JDK 自带剖析工具,功能齐全,如查看进行信息,快照转存,监控cpu,线程,办法区,堆等;

3.2 你晓得哪些JVM调优参数

  • -Xms128m JVM初始调配的堆内存
  • -Xmx512m JVM最大容许调配的堆内存,按需分配;
  • -XX:MetaspaceSize:调配给类元数据空间(以字节计)的初始大小;
  • -XX:MaxMetaspaceSize:调配给类元数据空间的最大值,超过此值就会触发Full GC
  • -XX:NewRatio:新生代和老年代的占比;
  • -XX:NewSize:新生代空间;
  • -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比;
  • -XX:MaxTenuringThreshold:对象进入老年代的年龄阈值;
  • XX:+PrintGC:打印 gc 信息;
  • -XX:+PrintGCDetails:打印 gc 详细信息

如果你对文中的知识点不太了解 举荐浏览周志明学生《深刻了解Java虚拟机:JVM高级个性与最佳实际(第3版)》和作者给出的官网链接!!!!