- 参数
- 启动参数
- Interview Question
- JVM垃圾回收器
- 说一说对JMM内存模型的理解?
- 请介绍类加载过程,什么是双亲委派模型?
- 常量池是什么?
- 直接内存是什么?
- 内存溢出和内存泄漏的区别 ?
- 如何监控和诊断JVM堆内和堆外内存使用?(未解决)
- 说一说JVM的组成?
- 说一说运行时数据区?
- 深拷贝和浅拷贝?
- Java垃圾回收机制?
- 老年代新生代默认比例?
- survivor区存在的意义?
- JVM 垃圾回收算法有哪些?
Serial GC 单线程的,进行垃圾收集过程中,会进入臭名昭著的“Stop-The-World”状态,从年代的角度,通常将其老年代实现单独称作 Serial Old,它采用了标记 - 整理(Mark-Compact)算法,区别于新生代的复制算法
ParNew GC,很明显是个新生代 GC 实现,它实际是 Serial GC 的多线程版本,最常见的应用场景是配合老年代的 CMS GC 工作,下面是对应参数
CMS(Concurrent Mark Sweep) GC,基于标记 - 清除(Mark-Sweep)算法,设计目标是尽量减少停顿时间,这一点对于 Web 等反应时间敏感的应用非常重要,一直到今天,仍然有很多系统使用 CMS GC。但是,CMS 采用的标记 - 清除算法,存在着内存碎片化问题,所以难以避免在长时间运行等情况下发生 full GC,导致恶劣的停顿。另外,既然强调了并发(Concurrent),CMS 会占用更多 CPU 资源,并和用户线程争抢
Parallel GC,在早期 JDK 8 等版本中,它是 server 模式 JVM 的默认 GC 选择,也被称作是吞吐量优先的 GC。它的算法和 Serial GC 比较相似,尽管实现要复杂的多,其特点是新生代和老年代 GC 都是并行进行的,在常见的服务器环境中更加高效。开启选项是
G1 GC 这是一种兼顾吞吐量和停顿时间的 GC 实现,是 Oracle JDK 9 以后的默认 GC 选项。G1 可以直观的设定停顿时间的目标,相比于 CMS GC,G1 未必能做到 CMS 在最好情况下的延时停顿,但是最差情况要好很多。G1 GC 仍然存在着年代的概念,但是其内存结构并不是简单的条带式划分,而是类似棋盘的一个个 region。Region 之间是复制算法,但整体上实际可看作是标记 - 整理(Mark-Compact)算法,可以有效地避免内存碎片,尤其是当 Java 堆非常大的时候,G1 的优势更加明显。
- 并行性:在垃圾回收期间,可以有效的利用多核cpu的计算能力。
- 并发性:垃圾回收器可以和引用程序交替执行的能力,所以并不会造成较长时间的阻塞。
- 分代GC:G1收集器同时兼顾老年代和年轻代
- 空间整理:G1在回收垃圾时会适当个的压缩对象,整理碎片空间,会在执行数次GC之后压缩region
- 可预见性:由于分区的原因,G1只选取部分区域进行内存回收,这样就缩小了回收范围。
优点: 可以在多核大内存的机器上可以实现指定的GC暂停时间,以及保存较高的吞吐量
场景:
- 可以让垃圾收集线程和应用程序线程并行执行,需要更多的CPU资源
- 容易预测的GC时间
- 不需要很高的吞吐量
Java内存模型的主要目标是定义程序中各个变量的访问规则,Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程不能对主内存中的数据进行操作,自能在自己的工作内存中操作主内存中数据的副本。
请介绍类加载过程,什么是双亲委派模型?首先,类的加载过程分为,加载,链接和初始化三个阶段。
加载阶段(loading)java会把从不同数据源比如jar文件,class文件等读取到的字节码文件加载到JVM中。
链接(linking)阶段分为验证、准备、解析三个阶段,主要是为了验证字节信息是否符合JVM规范,为类和接口中的静态变量作准备,分配内存空间,以及解析常量池中的符号引用,转换为直接引用。
初始化阶段(initialization),主要为了静态变量的赋值,初始化静态代码块等。
双亲委派模型(parents delegation model10),指的是当需要加载某一个类的时候,优先交给父类来加载,防止重复加载java类型。JDK 自带的加载器有:bootstrap class-loader, extension class-loader, application clss-loader
常量池是什么? 直接内存是什么?直接内存不是运行时数据区的一部分。属于堆外内存,直接内存申请空间耗费更高的性能,直接内存IO读写的性能要优于普通的堆内存
内存溢出和内存泄漏的区别 ?内存溢出 OutOfMemory,指程序在申请内存时,没有足够的内存空间供其使用。
内存泄露 Memory Leak,指程序在申请内存后,无法释放已申请的内存空间,内存泄漏最终将导致内存溢出。
如何监控和诊断JVM堆内和堆外内存使用?(未解决) 说一说JVM的组成?类加载器,执行引擎,运行时数据区,本地接口。其中执行引擎中包含及时编译器和GC,运行时数据区包含线程私有的程序计数器,JVM栈,本地方法栈和线程共享的堆,方法区。
说一说运行时数据区?- 每个线程都有一个程序计数器,程序计数器中保存的是当前线程正在执行字节码行号。
- 每个方法在执行的时候,都会在JVM栈中创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
- 本地方法栈:跟java虚拟机栈一样,但是是针对本地方法的
- 堆内存分为年轻代和老年代,年轻代分为eden,survivor1和survivor2. 几乎所有的对象实例和数组都在这里分配内存
- 方法区是所有线程共享的内存区域,它用于存储已被Java虚拟机加载的类信息、常量、静态变量、
即时编译器编译后的代码等数据
浅拷贝指的是”只是增加了一个指针指向已存在的内存地址“
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新
的内存
var arr1 = new Array(12,23,34) Var arr2 = arr1;//这就是一个最简单的浅拷贝
arr2[0] = 22 也会把 arr1[0]变为22
Java垃圾回收机制?JVM垃圾回收是通过一个GC守护线程来实现的也可以手动的通过System.gc来进行垃圾回收,通过可达性分析算法来判断哪些对象需要被回收,新创建的对象通常会在eden区,eden区没有足够空间后就会进行针对年轻代的minor GC,采用的是分代算法,然后存活下来的对象会到survivor的from区,surviv存活的对象在满足一定minorGC次数后会到老年代,有一些比较大的对象会直接进入老年代,老年代中内存不足时通常会发生majorGC,采用的是标记整理算法。
老年代新生代默认比例?2:1
survivor区存在的意义?减少去老年代对象的数量,减少majorGC。survivorfrom 和 survivorTo 两个区互相转换可以解决内存碎片化的问题。
JVM 垃圾回收算法有哪些?标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。
复制算法(年轻代):按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块
上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。
标记-整理算法(老年代):标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的
内存。



