jvm的垃圾回收过程讲解,字符字节位,jvm几个面试题

了解java虚拟机堆内存的分配策略

堆内存: 新生代(1个eden+2个survior)+老生代
New的对象首先进入eden中,经历一次minorGC后,如果对象还在则进入survior区域;其后每经过一次minorGC则会存活次数增加一个,到达一定的程度后进入老生代块中;
minorGC:对新生代堆块进行垃圾回收,因为此时大多数的对象都是朝生夕死,所以使用复制算法;
fullGC:对老生代区回收,因为死去的对象较少,所以使用标记整理算法.

新生代中为甚是两个survior

理解新生代的1个eden和2个survior,为什么是两个survior?假设两个survior分别是s1和s2
那么第一次minorGC:s1和s2都是空的,eden中有值,gc时eden中的存活对象会复制到s1;第二次gc,此时eden中的存活对象复制到s2,这些对象年龄统一为1,然后s1中的存活对象会将年龄加1,然后判断年龄是否足够大,足够大的进入老生代,别的进入s2,并且清空s1和eden;随后的gc与第二次gc相似;
从上面能够看出,eden和survior在minorGC时操作存在不同。

触发GC时机(什么时候)

minorGC触发:eden已满或者新建的对象已经没有空间可存
majorGC:

默认逻辑如下:minorGC之前,比较survior区域对象的大小和老生代剩余连续内存的大小,如果老生代剩余连续空间小于survior区域对象,会查询HandlePromotionFailure设置是否允许担保失败,如果不允许则直接进行进行majorGC,否则继续比较老生代剩余连续内存空间和历次晋升到老年代去的对象的平均大小,如果小于,则进行majorGC,否则尝试minorGC,如果失败也会fullGC;

fullFC:minorGC或majorGC失败的时候。

但是如果设置了 -XX:CMSInitiatingOccupancyFraction=65 参数,那么表示老生代的使用空间大于65%时就开始进行majorGc。而这个是推荐的做法。

有时候majorGc和fullGc已经区分的不清晰了,而且又是默认majorGC前会进行一次fullGc,所以界限就更模糊了。

被GC的对象(对什么东西)

如果对象到GC ROOTS 没有连接链,则该对象为不可达对象,应该被GC回收.

GC过程(做了什么事)

MinorGC:即youngGC使用复制算法,清除新生代中的不可达对象.一个eden区域,两个survivor区域,仅使用eden和一个survior区域,minorGC时,把eden和已使用survior中部分存活对象放入另一个survior中,另一部分年龄已够进入老生代,然后清理刚刚使用的eden和survior

MajorGC:仅处理老生带的空间,一般使用标记清除或标记整理算法
FullGC:清理整个堆空间包括新生代和老年代,老年代使用标记整理算法,清除老生代中的不可达对象.但此时一般会STW,采用serialGC回收器,很耗时,影响服务。


多线程时Eden区域的继续划分

Thread Local Allocation Buffer TLAB
jvm为每个线程分配的私有缓存区域,否则,多线程同时分配内存是,为避免操作同一地址,可能需要加锁等级制,进而影响共享速度。
如下图所示,start和end就是起止地址,top表示已经分配到哪里了。分配新对象,top移动。top和end相遇,表示缓存已满,会再分配。

jvm YGC频率很高的原因

代码system.gc:JVM安排GC运行, 还有可能完全被拒绝
框架原因:某些框架内部调用了gc方法
内存空间设置的太小
当构建的对象实例化十分频繁,或者对象较大
确实把大的对象放到内存里面去了,回收不了


GC很慢的原因

内存设置不合理
开始回收参数设置不对
回收器不合适
确实把大的对象放到内存里面去了,回收不了

字符 字节 bit知识补充

bit最小的单位 一个0或1的码就是一个bit
字节byte 1byte=8bit
byte声明方式:
// 声明一个占用1Mb内存的字节数组
byte b[] = new byte[1024*1024];          
int temp=0;
b[0]=(byte)temp;

字符char
声明方式 :char='d'
 a、A、中、+、*、の......均表示一个字符;
一般 utf-8 编码下,一个汉字 字符 占用 3 个 字节;
一般 gbk 编码下,一个汉字  字符  占用 2 个 字节;
java是用unicode来表示字符,"中"这个中文字符的unicode就是2个字节。

注意经常我们的的1M内存指的是,1M字节
即 1M=1024Kb=1024*1024byte=1024*1024*8bit

jvm几个面试题

为什么需要计数器?
多线程的执行需要cpu轮询处理,在线程切换的时候需要记住已经执行到哪里了

gcRoots有哪些?(两栈两方法)
栈中引用的对象
本地方法栈中引用的对象
方法区中常量引用的对象
方法区中静态属性引用的对象


虚拟机栈可以发生几种异常?oom在什么情况下发生?
两种 oom stackOverFlow
发生oom的情形:栈可以扩充,但是因为内存不够了,导致栈无法申请到内存

jvm如何分配直接内存, new对象如何不分配在堆而是栈上??
为何基本数据类型可以直接存在于栈中?
因为基本数据类型占用的空间大小一定

数组多大放在JVM老年代
该问题取决于你设置的jvm中eden和survior的大小,如果eden你设置的是512M,survior是256MB。那如果我声明一个600M的字节数组,那么该数组的内存一定直接分配到老年代
byte b[] = new byte[600*1024*1024];

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值