java内存、对象创建、回收流程

java的内存和默认空间大小

堆-Xms:默认四分之一的内存(4G物理内存就是1G)。其中新生代和老年代1:2。新生代中,eden和survior from、survior to 是8:1:1。

栈-Xss:默认512k-1024k。

方法区-XX:MetaspaceSize:默认21M(64位windows),最大值-1(不设上限)。jvm会自动调整。

类加载过程

1、判断是否加载类。

2、加载类,划内存空间。

如何划分空间?

一个是指针碰撞,连续的空间,默认使用这种

一个是空闲列表,非连续的空间。

如何解决并发同时创建空间的问题?

一个是CAS,一个是TLAB本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)

划分空间涉及到指针压缩、对象的内存分配流程等

3、初始化。符号引用转为直接引用,基础字段设置为零值

4、设置对象头。对象头、示例数据、对其填充。

5、执行init方法。程序员写的内容,程序员赋的值,与上面的零值不同,执行构造方法

指针压缩

64位中对象的地址值可以从64位,压缩到32位。2的32次方是4G,所以4G以下的内存,可以进行指针压缩,jvm会动态调整,默认开启。

对象的内存分配流程

1、在栈中分配——逃逸分析+标量替换。

对象进堆,但有特殊情况,是在栈中分配

如果方法中变量没有被外面的方法使用到(这是逃逸分析),而且这个变量(对象,可分可拆解)可以替换为标量(不可分不可拆解、java中就是基础类型int、boolean之类),即把对象(聚合量)中的成员变量(标量)拿出来,存到栈中,因为栈中可以存这些变量,但一般不能存对象(这就是标量替换)。这样对象就分配到栈中,而不是堆中,随着方法的结束、栈的结束而释放。

2、大对象直接进老年区。

3、不是大对象进eden区

不是大对象则进eden区,eden区满了,就minor gc,清空eden和survior from区,把剩下的数据放入survior to区,如果后面来的对象又把eden撑满了,则minor gc,清空eden和survior to 区,把剩下的数据放入survior from 区,form和to循环往复,如果from/to放不下,就放入老年区。如果老年区满了,就进行full gc。full gc是minor gc的10倍消耗。

4、长期存活对象进老年代

进入一次survior年龄就加一,15岁就进入老年代

5、对象动态年龄判断

如果好几个对象占用survivor50%以上,那这几个对象对应的年龄的数据进入老年代。这是因为15岁不一定准,那如何判断几岁呢?就用这个动态年龄,如果有多个数据大于50%,则说明这多个数据的年龄应该是一个门槛了,可以进入老年代了。

回收

堆满了回收的方法

引用计数法——不能解决循环引用的问题

可达性算法——gc root。根节点是本地方法栈的变量(系统的)、栈中本地变量(当前线程正在使用的)、静态变量(全局在使用的)

常见的引用类型

强引用new User(),gc不回收

软引用new SoftReference<User>(new User()),full gc后还是没空间,就会回收软引用,常用

弱引用new WeakReference<User>(new User()),gc直接回收,不常用

虚引用,不用

finalize()方法

如果是不可达对象,在回收前会走finalize方法。如果finalize方法重写了,且方法里面重新把对象引用上了,就不回收了,否则还是要回收

方法区回收的是无用的类,类没有实例、类的加载器被回收、类class对象没被使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值