• 3.JVM重要知识点


    一.三种JVM

    二.堆(重点)

    • 一个JVM只有一个堆内存,堆内存大小是可以调节的

    1.新生区

    目的:控制对象的诞生,成长和死亡

    分为:

    • 伊甸园区:所有对象都在伊甸园区new出来

    • 幸存0区和幸存1区:轻GC之后存下来的

    2.老年区(养老区)

    永久存在的对象放在老年区

    步骤:

    • 伊甸园区满了之后进行轻GC幸存下来的放到幸存0区或幸存1区

    • 当伊甸园区、幸存0区和幸存1区都满了进行重GC,幸存下来的放到养老区???

    • 当伊甸园区、幸存0区、幸存1区和养老区都满了,会出现OOM

    3.永久区

    注意:

    • 元空间是逻辑上存在而物理上不存在的,又称为非堆,但是实际上是和堆放在同一个物理空间中

    • 方法区中的一小块为常量区

    案例程序:

    • 默认情况下,JVM使用的最大内存为电脑总内存的四分之一,JVM使用的总内存为电脑总内存的十六分之一

    • 配置VM的参数: -Xms1024m -Xmx1024m -XX:+PrintGCDetails

    @Test
    public void test1() {
        //返回JVM试图使用的最大内存:默认情况下为电脑总内存的1/4
        long max = Runtime.getRuntime().maxMemory();
        //返回JVM的初始化总内存:默认情况下为电脑总内存的1/16
        long total = Runtime.getRuntime().totalMemory();
    
        System.out.println("max:" + max / (double) (1024 * 1024) + "MB");
        System.out.println("total:" + total / (double) (1024 * 1024) + "MB");
    
        //配置VM的参数: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
    }

     案例二:OOM

    • 配置VM的参数: -Xms8m -Xmx8m -XX:+PrintGCDetails

    public class JVMTest {
    
        public static void main(String[] args) {
            //配置VM的参数: -Xms8m -Xmx8m -XX:+PrintGCDetails
            String s = "aaaaaaaaaa";
            while(true){
                s += s + new Random().nextInt(999999999) + new Random().nextInt(888888888);
            }
        }
    }

     三.堆内存调优

    • 使用工具JProfiler

    • 内存快照分析工具:MAT(eclipse中使用),JProfiler

    • 作用:用于分析Dump文件,查找错误原因

    使用步骤:

    • IDEA中在插件库中下载插件JProfiler

    • 在网上下载JProfiler桌面工具破解并安装

    • 在IDEA中配置JProfiler

     编写会OOM的代码,并配置VM options

    编写程序

    • -Xms:设置初始化内存分配大小
    • -Xmx:设置最大分配内存
    • -XX:+PrintGCDetails:打印GC垃圾回收信息
    • -XX:+HeapDumpOnOutOfMemoryError:栈溢出信息生成Dump文件
    //-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
    public class Demo01 {
    
        byte[] array = new byte[1*1024*1024];   //1M
        public static void main(String[] args) {
            ArrayList<Demo01> list = new ArrayList<>();
    
            int count = 0;
    
            while(true){
                list.add(new Demo01());
                count++;
            }
        }
    }

    生成的dump文件在项目的目录下的xxx.hprof,双击打开

    使用工具排错

     四.GC

    • Eden与Survivor的内存大小比例为8:1:1

    1.引用计数法:

    • GC的时候会将计数器为0的对象C给销毁。

    2.复制算法

    • 幸存区from和幸存区to中谁是空的谁就是to,我们会将to中数据复制到from中保持to中数据为空

    • from和to区实际上为逻辑上的概念,保证to区一直空

    • 默认对象经过15次GC后还没有被销毁就会进入养老区

    流程:

    • 将Eden区进行GC存活对象放入空的To区,将From区存活的放到空的To区

    • 此时From区为空变成了To区,To区有数据变为From区

    • 经过15次GC后From区还存活的对象会被移动到养老区

    好处:没有内存碎片

    坏处:浪费了内存空间(To区为空)

    复制算法最佳使用场景:对象存活度较低(如果存活度较高,则From区空间全部被占满导致会将全部内容复制到To区)

    3.标记清除算法

    • 需要两次扫描,第一次扫描标记存活对象,第二次扫描清除没有被标记的对象

    优点:不需要额外的空间

    缺点:两次扫描严重浪费时间,并且还会产生内存碎片

    4.标记压缩算法

    • 在标记清除算法上进行优化,再扫描一次将存活对象移动到一起

    总结:

    五.JMM

    • Java Memory Model:java内存模型

  • 相关阅读:
    5.4.3 果园里的树
    5.3.2 字母重排
    5.3.1 6174问题
    Codeforces Round #253 (Div. 2), problem: (B)【字符串匹配】
    POJ1054 枚举【STL__binary_search()_的应用】
    432B
    0x3f3f3f3f...编程中无穷大常量的设置技巧
    2014年百度之星程序设计大赛 资格赛第一题 (longlong)
    Tarjan
    Dijkstra、Dij + heap、Floyd、SPFA、 SPFA + SLF Template
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12495247.html
Copyright © 2020-2023  润新知