四、java对象从new-内存分配-GC流程

对象的创建:

image.png

1.类加载检查

虚拟机字节码执行引擎执行jvm指令如果为new时,会查看方法区中常量池该类的符号引用,查看符号引用的类信息是否存在,如果不存在,则执行类加载过程。

2.加载类

执行类加载机制,通过双亲委派机制,使用类加载器加载类文件,验证字节码文件的完整性,将类中的静态变量赋值为初始值,将字面量的符号引用转换成直接引用,初始化赋值静态成员变量。

3.分配内存

分三种情况: 1.直接分配到old区(老年代) 2.分配到Eden区 3.分配在线程本地缓存区 分配内存的方式: 1.指针碰撞(默认使用)java堆中的内存规整的情况下,会将用过的内存和没用过的内存分开放置,将加载后计算好的类的大小,挪动类的大小的指针; 2.不规整的情况下 空闲列表(Free List) 如果内存为不规整的情况下,虚拟机就需要维护一个内存可用的列表,分配时从列表中查找,如果找到一块可用的内存,进行分配内存,并更新列表的状态 并发问题: 1.cas+失败重试: 在分配内存时可能被其他线程抢占分配,虚拟机会采用CAS+失败重试来保证内存分配的同步和原子性; 2.TLAB(Thread Local Allocation Buffer)线程本地缓冲区 在Eden 区会给每个线程分配一块小的内存,用来存储对象,是线程非共享的,只能当前线程访问,可使用­-XX:+UseTLAB开启,但是默认是开启状态;­XX:TLABSize可指定大小

4.初始化

内存分配后将对象实例变量初始化为初始值,例如int会初始为0,String 会初始为null;保证变量可以不用赋值就可以进行操作;

5.设置对象头

类在初始化后,会给对象进行设置,设置类的引用实例信息,还有在对象头中设置对象的hash值,对象的GC年龄,锁信息等; 对象在内存中的存储分为三个部分: 1.对象头 Object Header 对象头中分为两个部分,第一个为对象的运行时数据,包括对象的hashcode,锁的状态信息,是否偏量锁,对象被GC的分代年龄,第二个为类型指针,对类元信息的引用指针;(如果是数组对象的话,还有一个数组长度的数据部分) 2.实例数据 Instance Data 3.对象填充 Padding 个人理解:对象填充是优化对象存取速度,假设对象占用3个字节,会填充一个字节,改为为4个字节,4个字节存储起来速度是最优的; 指针压缩: -XX:-UseCompressedOops 关闭指针压缩,1.6以后默认开启指针压缩 32位系统一个对象指针占用的字节为4个,而64位操作系占用的为8个字节,在移动指针时性能较低,所以采用指针压缩方式,进而减少GC的压力;

对象在内存中的存储结构如下:

clipboard.png

对象的内存分配


image1.png

1.对象在栈上分配机制

对象在分配内存时,如上图所示,会先尝试在栈上分配内存,在分配之前,会有一个逃逸分析算法,他的作用呢也是优化垃圾对象尽快进入老年代的优化,大概逻辑为:判断对象是否会被外部引用,假设说有如下方法: 方法1: public void createUser(){ User user = new User(); } 方法2: public User createUser(){ User user = new User(); return user; } 方法1中只是创建了User对象,并没有对外返回User 对象,而方法2中将User返回了,调用方式时,肯定外部会对该对象的引用;所以当方式1执行时,可能就会分配在栈中,方法执行完 ,对象就会被回收了,而方法二中会有返回值,可能外部对它进行引用,则不会向栈中分配;jdk1.7以后默认开启逃逸分析; 全量替换: 当对象在认为在外部不会引用时,进一步分解时,虚拟机不会创建该对象,而是它的成员方法,变量分解为这个方法使用的成员变量,这样就不会因为栈中没有一块连续的空间而无法分配内存。 -XX:+EliminateAllocations jdk1.7以后默认开启全量替换;

2.tlab线程本地缓存区

如上图,如果会被外部所引用的情况下,虚拟机会首先判断是否为大对象,如果不是大对象的话,会尝试在Eden区中线程独有的一块区域中分配;

3.对象在Eden区分配机制

如果为大对象的话,会在Eden区进行分配内存,当Eden区的内存不足以存放该对象时,会出发minorGC/youngGc 年轻代的GC。 GC分为两种GC,一种是minorGC/youngGC,一种是majorGC/Full GC; minorGC负责对年轻代内存区域进行回收; majorGC负责老年代内存区域进行回收;

4.老年代分配担保机制

minorGC 后会计算老年代的内存空间,如果设置了一个参数“-XX:-HandlePromotionFailure” ,会判断之前minorGC后的平均内存如果大于老年代,如果大于的话会直接执行一次majorGC/Full GC,然后在执行minorGC。

5.对象动态年龄判断

个人理解:动态年龄判断机制,也就是说,在Eden区和survivor1区域gc复制对象时中假设说Survivor有三批对象,第一批对象占用10%,GC年龄为8,第二批对象占20%,GC年龄也为8,第三批 占用51%,通过虚拟机参数-XX:TargetSurvivorRatio可配置大小;它就会把第一批和第二批对象放进老年代;这个规则是想把对象尽早进入老年代,也是对jvm垃圾回收的一个优化;

6.大对象直接进入老年代

虚拟机为了优化垃圾回收,大对象会直接被分配到老年代,有个虚拟机参数-XX:PretenureSizeThreshold 可设置对象大小标准,如果超过这个标准会直接分配到老年代,而不会存放到年轻代,只针对于Serial和Parnew两个收集器的情况下有效;什么是大对象,需要连续的一块内存,例如字符串和数组;

7.长期存活的对象进入老年代

虚拟机给每个对象都标记了年龄,当在Eden区被gc后可以放到survivor区,这个对象接下来每次gc都会年龄+1,直到达到阙值后就会被放到老年代,通过-XX:MaxTenuringThreshold参数可以设置对象可存活的年龄。默认为15岁,CMS收集器的阙值为6岁。

对象的内存回收

1.引用计数器

这个算法是效率最高的,不过也有缺点,他的原理是,给对象添加一个计数器,每有一个引用就会计数器+1,如果释放了引用,就会-1;如果已经没有被引用后,他的计数器就会为0,就会被gc掉,可以又有这么一个问题: 有这么一段代码:思考 user1 和 user2 是否计数器会变为0; User user1 = new User(); User user2 = new User(); user1.property = user2; user2.property = user1; user 1 = null; user2 = null; user1 和user2的计数器是不会变为0的,以为他们相互引用;所以说基本上这个算法不会用上;

2.可达性分析算法

理解这么一个概念GC Root ,什么是GC Root,可以理解为祖宗,他是最高级别的对象,这个算法的原理就是,在执行gc时,会扫描,栈中的对象,类的静态变量,本地方法栈, 从GC Root开始查找引用的对象,如果有对该对象的引用,该GC Root就不会被标记为垃圾对象,其他的都会被标记为垃圾对象,等待被垃圾收集器所回收。如下图所示:


image2.png

扩充:

如何判断是一个无用的类

方法区主要回收无用的类分为三种:

1.堆中的对象已经被回收掉了
2.加载该类的classloader已经被回收了 
3.该类的java.lang.Class 对象已经没有存在引用关系,并且没有用反射获取方法和字段
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,976评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,249评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,449评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,433评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,460评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,132评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,721评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,641评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,180评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,267评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,408评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,076评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,767评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,255评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,386评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,764评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,413评论 2 358