我可是对着视频一个字一个字敲的,给我点赞,谢谢
视频直通车:www.ixigua.com/68962994383…
不止有JVM哦~高质量面试题。
什么情况下会发生栈内存的溢出?
答:
1)栈是线程私有的,栈的生命周期是和线程一样的。每当执行一个方法就会对应的创建一个栈帧。也叫作压栈操作。
2)栈帧包括,局部变量表、操作数栈、动态连接、方法出口等信息。
3)局部变量表包括方法参数和方法内部定义的局部变量信息。
4)当线程请求栈帧深度大于虚拟机栈允许的最大深度的时候,例如方法的递归调用。就会出现栈内存溢出。
5)可以通过jvm参数-Xss调整栈的内存大小。
说说jvm内存模型?
答:
1)jvm将虚拟机分成了五大区域 堆、虚拟机栈、方法区、本地方法栈、程序计数器
2)分别说出五个部分的基本作用
-
程序计数器,线程私有的,它是一块很小的内存空间可以作为当前线程 行号指示器,当前虚拟机正在执行的线程指令地址。不会发生内存溢出的情况。
-
虚拟机栈,线程私有的。每一个方法在执行的时候都会 创建一个栈帧。它保存了当前方法执行的 局部变量表、操作数栈、动态链接、方法出口等信息。
-
本地方法栈,线程私有的。保存的是native方法的相关信息。当执行的线程调用了本地方法,jvm是不会在虚拟机栈中创建栈帧的,而是简单的动态链接并直接调用此方法。
-
堆,所有线程共享的区域。几乎所有对象的实例和数组都是存放在这个区域。因此这个区域会经常垃圾回收的操作
-
方法区,它存放的是被加载后的的类信息、常量、静态变量、即时编译器、编译后的代码数据。从分代的角度来说它属于永久代。但是1.8之后就变成元空间了。
-
元空间不受java堆限制,而是与机器的内存相关。
jvm中一次完整的gc是什么样子的?如何晋升到老年代?
答:
1)java 堆分为 新生代和老年代;新生代又分为eden区和survivor from、survivor to[伊甸园区和幸存者区]区域 比例为8:1:1
2)当eden区满的时候就会触发一次minor gc 轻量级的gc,来收集新生代的垃圾。那么存活下来的对象呢就会被分配到幸存者 to区,然后采用复制算法将 from 区中的存放对象复制到to区域,然后身份转换 。并清理掉 eden区和to区。
3)如果有大对象的幸存,大对象需要连续的空间进行存储。会被直接存放到老年代区域。
4)对象在eden区出生,并且经历了一次minor gc 仍然存活,被存放到幸存者区的话。那么这个对象的年龄就会+1,此后呢每经历过一次gc 。并存活下来就会+1。默认是到达15次之后就会晋升到老年代。[年龄是可以通过参数设置的]
5)当老年代的空间不足时,就会触发一次full gc。full gc 的代价是昂贵的,它会清理堆和方法区的垃圾。生产中应当尽量减少full gc。
6)其中还有个major gc 是清理老年代的垃圾 ,他通常是伴随着minor gc 的。
jvm 中的担保机制是什么?老年代担保机制
答:
1)年轻代每次Minor GC之前JVM都会计算下老年代剩余可用空间,如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象)就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了
2)如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次Minor GC后进入老年代的对象的平均大小。
3)如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full GC ,对老年代和年轻代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生OOM
4)当然,如果Minor GC之后剩余存活的需要挪到老年代的对象还是大于老年代可用空间,那么也会触发Full GC ,Full GC完之后如果还是没有空间放Minor GC之后的存活对象,则会发生OOM
5)老年代分配担保机制担保的就是存在Full GC的情况下 减少一次Minor GC ,如果没有担保那么就是Minor GC->Full GC
聊一聊java中的垃圾回收算法?分别说说每种算法哪里使用?
答:
1)java中的垃圾回收算法呢一共有四种,分别是标记清除法、标记整理法、复制算法、分代收集算法。
标记清除法
1)首先是利用可达性分析遍历内存,将存活的对象进行标记。统一清除未标记的对象。
2)缺点就是效率不高,清除后呢会产生大量的不连续的空间碎片。如果在分配大对象的时候找不 到一块连续的空间存储对象,可能就会触发一次full gc。
- cms 在老年代,就是采用的标记整理算法,产生的空间碎片的话可以通过参数设置 -XX:+UseCMSCompactAtFullCollection 可以让jvm在执行完标记清除后再做整理 。
标记整理法
1)利用可达性分析,遍历内存。对存活的对象进行标记。然后将存活的对象向一端移动,边界以 外的对象呢就会回收掉。
2)特点就是不会产生碎片化空间,但是需要消耗整理空间的时间。适用于存活对象多,垃圾少的 场景。
3) Serial old、 Parallel 、G1
小结:标记清除和标记整理法的标记阶段的实现都是一样的。清除算法就是效率高,但是会有空间碎片 化;整理法呢就是效率低但是不会有空间碎片。
复制算法
1)将内存中按照容量的大小,划分相等的两块内存。就像我们内存中 幸存者区中的 survivor0与 survivor1两块相等的区域。每次呢只是用一块区域,每次发生minor gc 的时候。当已使用的一块内 存中还存活有对象的话,就直接复制到另一块区域。并直接清除当前区域,始终保持着一块区域完 全未使用。
2)特点呢就是不会产生空间碎片,效率也比较高。缺点就是浪费一块内存空间。
3)年轻代中幸存者区 Serial、 Parallel Scavenge 、ParNew
分代收集算法
1)根据对象的存活周期不同,把内存划分为不同的区域。比如java虚拟机中的新生代和老年代,就 是按照年龄划分的两个区域。
2)在新生代中,每次发生minor gc 并且会存活下来少量的对象,所以采用的是复制算法,只需要付出少量的复制代价。然后呢存活的对象年龄上就会+1,当年纪达到15的时候,就会晋升到老年代。
如何判断一个对象是否存活?
答:
1)jvm 有两种判断对象是否存活的方法,分别是:引用计数法、可达性分析法
引用计数法
1)它是给每个对象设置了一个引用计数器,当有一个地方引用该对象的时候计数器就会+1,引用失效 呢就会-1。当引用计数器为零的时候,说明这个对象就没有被引用 就是垃圾对象了,等待被回收。
2)缺点呢就是没有办法解决循环引用的问题。就是 a 对象引用了b,对象引用了a,此时这两个对象的引 用都不为0,但又不使用了,这时候就无法回收这两个对象。虚拟机就不会采用这种算法了。
可达性分析法
1)通过gc root 来作为起点,往下进行搜索。直到gc root 没有任何引用链,说明这个对象就是不可用 的。
2)仅满足上述条件并不会直接清除,会通过两次的标记,第一次是判断改对象有没有finalize()方法,如果没有这个方法会被标记成垃圾对象,等待回收。如果有这个方法就放入finalize()方法执行的队列中去,jvm 自行去执行,不保证一定会 执行。如果执行后任然没有被gc root 引用的话就会被回收掉。
3)可达性分析的话就是利用了标记清除这样一种算法。
哪些对象可以作为gc root 对象呢?
- 虚拟机栈中的引用对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用对象
- 本地方法栈中JNI引用对象
双亲委派十连击!
1、什么是双亲委派?
2、为什么需要双亲委派,不委派有什么问题?
3、"父加载器"和"子加载器"之间的关系是继承的吗?
4、双亲委派是怎么实现的?
5、我能不能主动破坏这种双亲委派机制?怎么破坏?
6、为什么重写loadClass方法可以破坏双亲委派,这个方法和findClass()、defineClass()区别是什么?
7、说一说你知道的双亲委派被破坏的例子吧
8、为什么JNDI、JDBC等需要破坏双亲委派?
9、为什么TOMCAT要破坏双亲委派?
10、谈谈你对模块化技术的理解吧!
以上10道题的答案请移步 hollis 大神的博客。
作者:HollisChuang
链接:juejin.cn/post/691631…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更多JVM好文章请移步到我的个人掘金收藏夹(看我写的也可以哇~),绝对都是精品文章。