ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【JVM】详解HotSpot、堆与OOM的原理并实现

2021-12-23 18:31:29  阅读:236  来源: 互联网

标签:OOM 虚拟机 HotSpot 永久 XX GC 内存 JVM


目录

参考文章

三种JVM

1.Sun        HotSpot        

2.BEA        JRockit

3.IBM        J9 VM

堆(Heap)

堆内存的划分

永久代的演变

方法区与永久代/元空间

Minor GC和Full GC的触发条件

OOM(Out Of Memory)

JVM堆常用配置参数

JVM堆初始内存大小


参考文章

 JVM系列-05-方法区-永久带VS元空间_hylexus的博客-CSDN博客_jvm方法区和元空间

Java堆内存又溢出了!教你一招必杀技【附源码】_李振良_阿良_51CTO博客

Java GC种类和触发时机_u011833033的博客-CSDN博客_gc触发时机

JVM(六)JVM优化之常用参数_jwang的博客-CSDN博客_jvm常用调优参数

三种JVM

1.Sun        HotSpot        

        我们学习和是用的都是Sun公司旗下的HotSpot虚拟机,可以通过cmd查看java版本看到

java -version

 

Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

2.BEA        JRockit

3.IBM        J9 VM

我们学习的都是:HotSpot

堆(Heap)

在JVM中,java虚拟机栈和本地方法栈都是线程级别的,既每个线程都有对应的本地方法栈和java虚拟机栈

但是堆和方法区,在JVM只有一个,而且堆内存的大小是可以调节的。

可以在IDEA运行设置中配置虚拟机参数和配置程序参数

堆内存的划分

堆内存中被细分为三个区域,分别为

        1.年轻代(Young Generation),年轻代又可划分,其中生成区和幸存区的容量大小为8:1:1

                1.生成区(伊甸园区)(Eden)

                2.幸存区(Survivor),幸存区又可划分为

                        1.幸存0区(FromSpace)

                        2.幸存1区(ToSpace)

        2.老年代(Old Generation)

        3.永久代/元空间(Permanent Generation/MetaSpace

这里永久代和元空间并不能完全划等号

永久代的演变

        jdk1.6之前:是永久代,常量池是在方法区

        jdk1.7        :  是永久代,但是慢慢退化了,常量池在非堆中

        jdk1.8之后:没有永久代,代替的是元空间,常量池在非堆中

        元空间和永久代最大的区别在于:元空间不在虚拟机设置的内存中,而是使用了本地内存

        这一点也可以在模拟中看到

        当我们配置JVM内存时,将最大内存和初始内存设为1M,并输出GC过程

 -Xms1m -Xmx1m -XX:+PrintGCDetails

 我们可以看到年轻代合老年代在虚拟机中的总占比为1.5M

 

 这时虚拟机的内存也为1.5M,说明在jdk1.8中,元空间并不占用jvm内存

方法区与永久代/元空间

        方法区和元空间之间的关系非常模糊,方法区和永久代并不等价,但是可以牵强的解释两者等同,但是还是不同的,方法区更类似一个标准,而永久代/元空间实现了这个标准,这就相当于java中接口和接口实现一样,下文有些时候也会将两个等同

Minor GC和Full GC的触发条件

        1.当生成区(伊甸园区)(Eden)满后,会触发Minor GC,然后将不能删除的放入幸存区

至于幸存区如何进入老年代,这篇文章给出了解释

        2.该文章指出,当对象在幸存区经历了15次Minor CG后,就会被晋升到老年代,这个15也是可以配置的

        3.当老年代满后,会触发Full GC,清理老年代

        4.当老年代也无法被清理的时候,就会抛出OOM异常

 

OOM(Out Of Memory)

        根据名称就可以很清晰的看出,就是java程序在运行时内存超限了,堆中无法存放

        我们可以手动模拟一下堆的溢出(OOM),因为真正内存溢出对于普通的程序较困难实现,所以我们可以将JVM分配的内存手动减少来实现

        首先先将JVM的初始分配内存和最大分配内存都设置为2m

        然后运行如下代码

public class Main {
    public static void main(String[] args) {
        String str="123";
        while(true){
            str+=new Random().nextInt(12345678)+new Random().nextInt(999999999)+new Random().nextInt(999999999);
        }
    }
}

         代码的作用是无限向str随机拼接数据,直到程序无法继续运行,最后就会报出OOM

JVM堆常用配置参数

参考文章

1.Java堆参数

-Xms:表示初始堆大小(常用)

例如:-Xms1024m 就代表初始堆大小为1024m

-Xmx:表示最大堆大小(常用)

-Xmn:表示年轻代大小

-XX:NewRatio:设置年轻代和老年代的比值

例如:-XX:NewRatio=3,表示年轻代:老年代 = 1:3,年轻代占1/4

-XX:SurvivorRatio:设置Egen区和两个Survivor区的比值

例如:-XX:SurvivorRatio=3,表示Egen区:两个Survivor区 = 3 :2,一个Survivor区占1/5

-XX:PermSize:设置永久区初始大小,JDK1.8起无效

-XX:MaxPermSize:设置永久区的最大值,JDK1.8起无效

-XX:MetaspaceSize:初始元空间大小,JDK1.8起有效

-XX:MaxMetaspaceSize:元空间的最大值,JDK1.8起有效

2.垃圾收集器参数

-XX:+UseSerialGC:虚拟机运行在Client模式下的默认值,Serial+Serial Old

-XX:+UseParNewGC:ParNew+Serial Old,在JDK1.8被废弃

-XX:+UseConcMarkSweepGC:ParNew+CMS+Serial Old,Serial Old 收集器将作为 CMS 收集器出现 Concurrent Mode Failure 失败后的后备收集器使用

-XX:+UseParallelGC:虚拟机运行在Server模式下的默认值,Parallel Scavenge+Serial Old(PS Mark Sweep)

-XX:+UseParallelOldGC:Parallel Scavenge+Parallel Old

-XX:+UseG1GC:G1+G1

3.跟踪参数

-XX:+PrintGC:获取GC的初步信息

-XX:+PrintGCDetail:打印GC的详细信息

-XX:+PrintGCTimeStamps:打印GC发生的时间戳

JVM堆初始内存大小

package com.sty;

import java.util.Random;

public class Main {
    public static void main(String[] args) {
        //jvm虚拟机试图调用的最大内存
        long maxMemory = Runtime.getRuntime().maxMemory();
        //返回jvm的总内存
        long totalMemory = Runtime.getRuntime().totalMemory();
        System.out.println("maxMemory字节为:"+maxMemory+"     内存为:"+maxMemory/1024*1.0/1024*1.0+"M");
        System.out.println("totalMemory字节为:"+totalMemory+"     内存为:"+totalMemory/1024*1.0/1024*1.0+"M");
    }
}

通过如下代码,运行可以得到jvm虚拟机试图调用的最大内存和返回jvm的总内存

 一般来说,试图调用的最大内存为系统内存的1/4,返回jvm的总内存为系统最大内存的1/64。

标签:OOM,虚拟机,HotSpot,永久,XX,GC,内存,JVM
来源: https://blog.csdn.net/Elephant_King/article/details/122110220

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有