jvm学习(二) 堆内存简介

jvm学习(二) 堆内存简介,第1张

jvm学习(二) 堆内存简介

堆内存(heap):

一个JVM实例只有一个堆内存,堆也是Java内存管理的核心区域,堆在JVM启动的时候创建,其空间大小也被创建,是JVM中最大的一块内存空间,所有线程共享Java堆,物理上不连续的逻辑上连续的内存空间,几乎所有的实例都在这里分配内存,在方法结束后,堆中的对象不会马上删除,仅仅在垃圾收集的时候被删除,堆是GC(垃圾收集器)执行垃圾回收的重点区域。

堆空间细分:

Java7及以前将堆空间逻辑上分成三部分:新生区+养老区+永久代

Java8及以后将堆内存逻辑上分为:新生区+养老区+元空间

新生代:

1.新生代使用了复制算法
2.新生代为gc的重点对象,经官方测试70%对象都生命周期都会在新生代中完结
3.新生代又分为了eden、survivor1、survivor2,对象创建先放在eden中,经过一定时间还幸存就会放在幸存者区
4.内存比例分默认为:8:1:1
5.新生代收集器:Minor GC/Young GC

eden(新生区):

当初始加载对象时会进入新生区

survivor(幸存区):

1.幸存区又分为from 和 to —谁为空谁为to ,始终都会有一个区域为空。

2.幸存区不会主动进行垃圾回收,只会eden回收时才会附带进行gc

3.当在幸存区中的阈值达到了15后(默认15可修改)会自动进入老年代(当然也会有特殊的优化:如当survivor区域中相同年龄的内存总和大于survivor的一半内存,会将大于等于平均年龄的对象提前放入老年代)

4.当新生区(eden)出现了内存不足时,会进行YGC,那么会将没有指针的对象回收,还有指针引向的对象放入survivor1或者survivor2区域中,eden清空,数据放入一个survivor中。当第二次进行gc那么会将eden数据放入另一个空的survivor中,并且将当前survivor中有效数据,放入空的survivor中,以此类推。

老年代:

1.较大的对象数据会放入老年代

2.当在幸存区中的阈值达到了15后(默认15可修改)会自动进入老年代 

3.老年代的数据都是相对于持久的不会频繁的gc

4.(MajorGC / Old GC) 在进行majorgc时会至少进行一次minorGc ,而且majorgc的效率是比minorGc 慢10倍的
5.老年代收集器:MajorGC / Old GC 要区分与Full GC

我的理解:新时代的区域垃圾回收效率会比较高,老年代的垃圾回收效率通常会很低,垃圾回收会触发STW(stop the world),应该尽量避免老年代频繁GC.如果对象在EDEN出生并且经过一次MinnorGC后依然存活,并且能被Survivor容纳的话,将会被放在幸存者区,并将对象年龄设为1,每熬过一次MinnorGC,age增加一岁,当age增加到15时,会被放入老年代

GC ROOTS : 

在java语言中,可以作为GC ROOTS的对象包括下面几种:

1.虚拟机栈(栈帧中的本地变量表)中引用的对象

2.方法区中类静态属性引用的对象

3.方法区中常量引用的对象

4.本地方法栈中JNI(一般说的是Native方法)引用的对象

我的理解:被GC ROOTS所持有的对象不会被垃圾回收器回收

 jvm堆内存查看工具: jvisualvm

工具-插件   安装GC插件

代码

import java.util.ArrayList;
import java.util.List;

public class HeapTest {

    public static void main(String[] args) {
        List list = new ArrayList<>();
        while (true){
            list.add(new HeapTest());
        }
    }
}

用jvisualvm的GC插件可以看到如下

 

因为HeapTest不断的被创建,又被GC ROOTS引用,没办法回收,所以当堆内存满了以后会抛出异常

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5606566.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存