面试系列之JVM

说说JVM的内存模型?

方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据

堆:存放对象实例,几乎所有的对象实例都要在堆上分配

程序计数器:当前线程所执行的字节码的行号指示器

虚拟机栈:描述的是Java方法执行的内存模型

本地方法栈:为虚拟机使用到的native方法服务

 

讲讲什么情况下回出现内存溢出,内存泄漏?

内存溢出 out of memory:指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory(比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出);

内存泄露 memory leak:指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光,最终内存泄漏将导致内存溢出;

 

常见JVM启动内存参数设置?

-Xms:设置java程序启动时初始堆内存大小

-Xmx:设置java程序能获得的最大堆内存大小

-Xmn:可以设置新生代的大小

-XX:PermSize 设置非堆内存初始值(JDK8版本开始移出)

-XX:MaxPermSize 设置最大非堆内存的大小(JDK8版本开始移出)

 

聊聊MinorGC 和FullGC?

MinorGC发生在新生代的垃圾收集动作,当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了;

FullGC发生在老年代的垃圾收集通常发生Full GC意味着至少发生了一次Minor GC(直接出生早老年代的除外),Full GC因为都是大对象回收,所以通常速度要比Minor GC慢很多;

 

JVM中大对象如何进行分配?

大对象,指的就是需要大量连续内存空间的Java对象,比较典型的大对象就是那种很长的字符串以及数组,经常出现大对象容易导致当内存空间还有很多的时候就提前触发收集器收集以获取足够连续的内存空间;

虚拟机提供一个可控制的参数:-XX:PretenureSizeThreshold来设置对象直接进入老年代的阈值,当对象大于这个值直接进入老年代,这样做是为了避免在Eden区和Survivor区之间发生大量的内存复制;

 

如果A和B对象循环引用,是否可以被GC?

判断一个对象是否会被GC主要是判断该对象的引用链中是否有关联对象跟GC ROOT根相关联,如果没有跟root关联,即使A和B循环关联,AB也会被GC处理掉;

 

jvm gc如何判断对象是否需要回收,有哪几种方式?

引用计数算法和可达性分析算法

 

Java中能不能主动触发GC?

可以,调用System.gc(),但是该方式不会立即使JVM触发GC,只是通知JVM尽快执行GC,具体还是由JVM自己调度;

 

垃圾回收算法有哪些?

引用计数:在对象被其他对象所引用时计数器加1,而当引用失效时则减1,缺点:无法处理循环引用的情况,还有就是每次进行加减操作比较浪费系统性能;

标记-清除:分为标记和清除两个阶段:首先标记出所有需要回收的对象,然后统一回收掉所有标记的对象,缺点:存在空间碎片问题,这种情况下,当程序在后期运行过程中需要分配较大对象时,无法找到足够的连续内存,而不得不提前触发垃圾回收,不连续的内存空间的工作效率要低于连续的内存空间;

复制算法:将内存等分成2块,每次只使用其中一块在垃圾回收时,将正在使用的内存中的存留对象复制到未被使用的内存块中去,之后去清除之前正在使用的内存块中所有的对象,反复去交换俩个内存的角色,完成垃圾收集,此算法不需要考虑内存碎片问题,缺点:真正可用的内存其实只有总内存1/2(Java中新生代的from和to空间就是使用这个算法);

标记-压缩:标记-压缩算法是在标记-清除的基础上做的优化,也是先标记,但是标记完不是直接清理,而是先压缩,把存活的对象压缩到内存的一端,然后再将存活对象端边界以为的内存对象直接清理掉,减少了空间碎片问题,同时也解决了复制算法的1/2内存牺牲问题;

分代收集算法:根据对象的存活周期不同,将内存划分为N块,然后根据每个内存的特点使用不同的算法;

分区算法:将整个内存分为N多个小的独立空间,每个小空间都可以独立使用,这样细粒度的控制一次回收多少个小空间和哪些小空间,而不是对整个空间进行GC,从而提升性能,并减少了GC的停顿时间

 

JVM是怎么进行垃圾回收的?

一般将Java堆分为新生代和老年代,在新生代每次收集有大量对象死亡,只有少量对象存活,比较适合复制算法(牺牲少量存活对象的复制为代价就能完成收集),老年代中因为对象存活率高,没有额外的空间使用,就必须使用标记-清除或者标记-压缩算法来进行回收

新生代:新生代的对象生死周期比较短,新生代将内存分为一块较大的Eden区和两块较小的Survivor区,每次使用Eden和其中的一块S1,当垃圾回收时,将Eden和S1中还存活的对象一起拷贝到另一块S2上,最后清除掉Eden和S1区;

 

Java的类加载机制,什么是双亲委派?

类加载生命周期:

双亲委派:某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载;

 

JVM堆和栈的区别?

堆主要放new的对象,而栈放基本类型和句柄,句柄指向的是堆

垃圾回收的时候回收的是堆,栈比较难回收,一般不回收

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值