JVM面试连环炮

目录


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

会。自己实现堆载的数据结构时有可能会出现内存泄露,程序运行过程中会不断地分配内存空间;那些不再使用的内存空间应该即时回收它们,从而保证系统可以再次使用这些内存。如果存在无用的内存没有被回收回来,那就是内存泄露。

2 64 位 JVM 中,int 的长度是多数?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。

3 Serial 与 Parallel GC 之间的不同之处?

Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认 的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行。

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

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

5 Java 中 WeakReference 与 SoftReference 的区别?

虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一 旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不 足的时候。

6 JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要 使用

当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从32 位增加到了 64 位,因此 堆内存会突然增加,差不多要翻倍。这也会对 CPU缓存(容量比内存小很多)的数据产生不利的影响。 因为,迁移到 64 位的 JVM主要动机在于可以指定最大堆大小,通过压缩 OOP 可以节省一定的内存。 通过-XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。

7 怎样通过 Java 程序来判断 JVM 是 32 位 还是 64位?

你可以检查某些系统属性如 sun.arch.data.model 或 os.arch 来获取该信息。

8 32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?

理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之 间不同,如 Windows 系统大约 1.5 GB,Solaris 大约3GB。64 位 JVM 允许指定最大的堆内存,理论上 可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

9 由浅入深理解JVM虚拟机

由浅入深理解JVM虚拟机

10 Java方法四种引用

Java方法四种引用

11 JVM底层预备知识GC

JVM底层预备知识GC

12 OSGI(动态模型系统)

OSGi(Open Service Gateway Initiative),是面向 Java 的动态模型系统,是 Java 动态化模块化系统的 一系列规范。

13 动态改变构造

OSGi 服务平台提供在多种网络设备上无需重启的动态改变构造的功能。为了最小化耦合度和促使这些 耦合度可管理, OSGi 技术提供一种面向服务的架构,它能使这些组件动态地发现对方。

14 模块化编程与热插拔

OSGi 旨在为实现 Java 程序的模块化编程提供基础条件,基于 OSGi 的程序很可能可以实现模块级的热 插拔功能,当程序升级更新时,可以只停用、重新安装然后启动程序的其中一部分,这对企业级程序开 发来说是非常具有诱惑力的特性。

OSGi 描绘了一个很美好的模块化开发目标,而且定义了实现这个目标的所需要服务与架构,同时也有 成熟的框架进行实现支持。但并非所有的应用都适合采用 OSGi 作为基础架构,它在提供强大功能同 时,也引入了额外的复杂度,因为它不遵守了类加载的双亲委托模型。

15 什么时候会触发FullGC

除直接调用System.gc外,触发Full GC执行的情况有如下四种。
1 旧生代空间不足
旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:
java.lang.OutOfMemoryError: Java heap space
为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在 新生代多存活一段时间及不要创建过大的对象及数组。

2 Permanet Generation空间满
PermanetGeneration中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的 方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
java.lang.OutOfMemoryError: PermGen space
为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。

3 CMS GC时出现promotion failed和concurrent mode failure
对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和 concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。

promotionfailed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧 生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生 代,而此时旧生代空间不足造成的。

应对措施为:增大survivorspace、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的 版本中有可能会由于JDK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种 状况,可通过设置-XX:CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。

4 统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不 足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的 平均大小大于旧生代的剩余空间,那么就直接触发Full GC。

例如程序第一次触发MinorGC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时, 首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,则执行Full GC。

当新生代采用PSGC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一 次Minor GC后,PS GC会检查此时旧生代的剩余空间是否大于6MB,如小于,则触发对旧生代的 回收。除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一 小时执行一次Full GC。可通过在启动时通过- java-Dsun.rmi.dgc.client.gcInterval=3600000来设 置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc

16 什么是Java虚拟机?为什么Java被称作是“平台无关的编程语 言”?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节 码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或 者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

17 对象分配规则

  1. 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。

  2. 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在 Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。

  3. 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次 Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到 阀值对象进入老年区。

  4. 动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一 半,年龄大于或等于该年龄的对象可以直接进入老年代。

  5. 空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如 果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设 置,如果true则只进行Monitor GC,如果false则进行Full GC

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

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的 Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java 程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。

类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后 产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。

当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值) 和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化

包括:
1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;
2)如果类中存在初始化语句,就依次执行这些初始化语句。 类的加载是由类加载器完成的,类加载器包 括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加 载器(java.lang.ClassLoader的子类)。

从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的 安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。 类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向 Java程序提供对Bootstrap的引用。

下面是关于几个类加载器的说明
Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap; System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量 classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

19 Java对象创建过程

1.JVM遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引 用。然后加载这个类(类加载过程在后边讲)

2.为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程缓冲分配
(TLAB)”

3.将除对象头外的对象内存空间初始化为0

4.对对象头进行必要设置

20 简述Java的对象结构

Java对象由三个部分组成:对象头、实例数据、对齐填充。

对象头由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、线 程持有的锁、偏向线程ID(一般占32/64 bit)。第二部分是指针类型,指向对象的类元数据类型(即对 象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。

实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的)
对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐 )

21 如何判断对象可以被回收

判断对象是否存活一般有两种方式:

引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时 可以回收。此方法简单,无法解决对象相互循环引用的问题。

可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当 一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,不可达对象。

22 JVM的永久代中会发生垃圾回收么

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如 果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小 对避免Full GC是非常重要的原因。请参考下Java8:从永久代到元数据区 (注:Java8中已经移除了永久 代,新加了一个叫做元数据区的native内存区)

24 调优命令有哪些?

Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo

  1. jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
  2. jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机 进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
  3. jmap,JVM Memory Map命令用于生成heap dump文件
  4. jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了 一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
  5. jstack,用于生成java虚拟机当前时刻的线程快照。
  6. jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数

25 JVM调优工具

JVM自带内存分析工具实战
JVM内存分析工具JProfiler的安装和使用

26 Minor GC与Full GC分别在什么时候发生?

新生代内存不够用时候发生MGC也叫YGC,JVM内存不够的时候发生FGC

27 你知道哪些JVM性能调优

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

上一篇:Java 进阶 07 —— JVM 垃圾回收相关概念


下一篇:寒假总结