前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

jvm堆

作者头像
逍遥壮士
发布2021-04-29 11:21:37
3720
发布2021-04-29 11:21:37
举报
文章被收录于专栏:技术趋势技术趋势

继上文:深入方法区


java堆,属于内存中最大的一块,也是常见OOM发生地,大部分对象的实例都是在这里分配内存,当然随着逃逸分析技术的日益强大,栈上分配、标量替换也是可以直接分配对象内存的,所以不是所有的java实例都是在堆中分配。

java堆的内存结构是什么?

注意以上是1.8及以上的版本内存结构,jdk1.8以前是永久代。

堆空间有:年轻代、老年代、元空间

年轻代分为伊甸元区(Eden)和Survivor区(幸存区) 点整个堆空间的 1/3;

伊甸元区(Eden)

Survivor区又分为:S0(from)、S1(to)

edn:S0:S1之间的比例是:8:1:1

老年代占整个堆空间的 2/3

元空间属于堆外空间也是方法区;

几种垃圾回收的区别?

年轻代发生的GC叫Minor GC,老年代发生的GC叫Major GC,Full GC是清理整个空间包括年轻代和老年代;

Minor GC

若发现edn空间已满,则进行Minor GC,通过可达性算法分析,将垃圾对象进行回收edn和Survivor 0,然而如果不是垃圾会被移入Survivor 1,当下次edn又满了,那会将 edn及Survivor1 进行回收,把不是垃圾放到Survivor 0也就是说每次会将Survivor 中一个进行回收将不回收放到另一个Survivor。

当某个对象回收次性达15次(jvm默认),会自动放到老年代中。

Major GC

Major GC这个是不确定的,在oracle或相关资料了解发现,这个Major GC触发前至少会触发一次Minor GC并且这个Major GC比Minor GC慢10倍。

Full GC

手动调用Sytem.GC()

老年代空间不足时

GC担保失败

Full GC这个触发一般触发条件是,手动调用、老年代最大可用空间小于现在新生代对象空间,还有担保空间发现不足,这几种都需要进行Full GC。

注意:不管内存怎么收,只是将某个位置标记为可用,新的对象直接覆盖原来的位置,而不是真的把对象清掉,回收只是将空闲表上面标记为可用。

(以上图来自互联网)

JVM参数配置

参数 描述

-Xms:

堆内存初始大小

-Xmx:

MaxHeapSize设置堆的最大空间大小

-Xmn:

设置年轻代大小

-XX:NewSize(-Xns)

年轻代内存初始大小

-XX:MaxNewSize(-Xmn)

设置新生代最大空间大小方法区

-XX:NewRatio

新生代和老年代的比值,值为4新生代:老年代=1:4,即年轻代占堆的1/5

-XX:SurvivorRatio=8

年轻代中Eden区与Survivor区的容量比例值,默认为8

-XX:+HeapDumpOnOutOfMemoryError

内存溢出时,导出堆信息到文件

-XX:+HeapDumpPath

堆Dump路径

-XX:OnOutOfMemoryError

当发生OOM内存溢出时,执行一个脚本

-XX:MaxTenuringThreshold=7

表示如果在幸存区移动多少次没有被垃圾回收,进入老年代

TLAB是什么?

TLAB全称Thread Local Allocation Buffer,中文名称是:本地线程缓存区,主要的作用是专门用来分配内存避免多线程间的冲突,这个TLAB是在eden中的占1%,当分配对象的时候先尝试栈上分配,不成功则继续TLAB分配,不成功则直接进入老年代。

java堆是连续的吗?

java堆理论上是连续的,但是官方给出来的说法是非连续的,整体是连续,但是存在不连续的地方。

模拟内存溢出实例

如果计算需要的堆多于自动存储管理系统可以提供的堆,则Java虚拟机将抛出一个 OutOfMemoryError。

代码语言:javascript
复制
/**
 *
 * 功能描述: 测试OOM的问题
 * -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails
 *
 * @param:
 * @return:
 * @auther: csh
 * @date: 2020/12/3 15:01
 */
public class OOME {

    static class OOMObject {
    }

    public static void main(String args[]) {
        List <OOMObject> list = new ArrayList <OOMObject>();
        while (true) {
            list.add(new OOMObject());
        }
    }
}
代码语言:javascript
复制
[GC (Allocation Failure) [PSYoungGen: 5101K->488K(6144K)] 5101K->2836K(19968K), 0.0030660 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 6120K->480K(6144K)] 8468K->6979K(19968K), 0.0058824 secs] [Times: user=0.08 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 6112K->488K(6144K)] 12611K->12594K(19968K), 0.0073455 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 488K->0K(6144K)] [ParOldGen: 12105K->10620K(13824K)] 12594K->10620K(19968K), [Metaspace: 3450K->3450K(1056768K)], 0.1760388 secs] [Times: user=0.39 sys=0.00, real=0.18 secs] 
[Full GC (Ergonomics) [PSYoungGen: 5632K->511K(6144K)] [ParOldGen: 10620K->13627K(13824K)] 16252K->14139K(19968K), [Metaspace: 3450K->3450K(1056768K)], 0.1199610 secs] [Times: user=0.44 sys=0.00, real=0.12 secs] 
[Full GC (Ergonomics) [PSYoungGen: 3063K->2857K(6144K)] [ParOldGen: 13627K->13627K(13824K)] 16690K->16484K(19968K), [Metaspace: 3450K->3450K(1056768K)], 0.1521509 secs] [Times: user=0.75 sys=0.01, real=0.15 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 2857K->2857K(6144K)] [ParOldGen: 13627K->13609K(13824K)] 16484K->16466K(19968K), [Metaspace: 3450K->3450K(1056768K)], 0.1254353 secs] [Times: user=0.56 sys=0.02, real=0.13 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid9668.hprof ...
Heap dump file created [28238817 bytes in 0.089 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  at java.util.Arrays.copyOf(Arrays.java:3210)
  at java.util.Arrays.copyOf(Arrays.java:3181)
  at java.util.ArrayList.grow(ArrayList.java:265)
  at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
  at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
  at java.util.ArrayList.add(ArrayList.java:462)
  at com.jvm.oom.OOME.main(OOME.java:23)
Heap
 PSYoungGen total 6144K, used 3016K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 5632K, 53% used [0x00000000ff980000,0x00000000ffc72028,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen total 13824K, used 13609K [0x00000000fec00000, 0x00000000ff980000, 0x00000000ff980000)
  object space 13824K, 98% used [0x00000000fec00000,0x00000000ff94a580,0x00000000ff980000)
 Metaspace used 3482K, capacity 4500K, committed 4864K, reserved 1056768K
  class space used 379K, capacity 388K, committed 512K, reserved 1048576K

从上列可以看出,先经过三次PSYoungGen,也就是所说的Minor GC,然后再经历过多次Full GC ,最后内存溢出。

最后

由于堆中的东西实在太多了,本文算是一个基础入门后需到内存和垃圾回收到重点深入,并且可结合各种场景来深入更好。

参考文章:

https://www.cnblogs.com/nyhhd/p/12641370.html

系列文章:

jvm相关知识

java发展史及虚拟机历史

对象的内存是如何布局的?

jvm的类加载器(classloader)及类的加载过程

java模块化系统

深入栈帧

深入方法区

...

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档