• jvm


    jvm体系结构

    黄色:所有线程共享、占用空间较大,存在垃圾回收

    灰色:各个线程独享数据区域、占用空间较小,不存在垃圾回收

    1575783857812

    类装载器ClassLoader

    是什么

    负责加载class文件,class文件在文件开头有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责class文件的加载,至于它是否可以运行,则有Execution Engine决定。

    1575784373433

    类装载器类型

    虚拟机自带的加载器

    • 启动类加载器(Bootstrap)C++
    • 扩展类加载器(Extension)Java
    • 应用程序类加载器(AppClassLoader)Java也叫系统类加载器,加载当前应用的classpath的所有类

    用户自定义加载器

    • Java.lang.ClassLoader的子类,用户可以定制类的加载方式

    1575784997347

    演示一

    1575790437359

    双亲委派

    双亲委派模型的式作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完全这个加载请求时,子加载器才会尝试自己去加载。

    沙箱安全

    沙箱机制是由基于双亲委派机制上 采取的一种JVM的自我保护机制,假设你要写一个java.lang.String 的类,由于双亲委派机制的原理,此请求会先交给Bootstrap试图进行加载,但是Bootstrap在加载类时首先通过包和类名查找rt.jar中有没有该类,有则优先加载rt.jar包中的类,因此就保证了java的运行机制不会被破坏

    演示二

    1575790989071

    本地接口

     本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为native的代码,它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载native libraties

      目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或着Java系统管理生产设备,在企业级应用中已经比较少见。应为现在的异构领域间的哦通信很发达,比如可以使用Socket通信,也可以使用Web Service等等,不多做介绍。

    本地方法栈

     它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法库。

    演示三

    线程的start方法调用了start0方法就是一个本地方法,只有声明没有实现

    1575791717214

    程序计数器

    类似排班值日表

    1575791524021

    方法区

    • 所有线程共享,存在垃圾回收
    • 存类模板信息(Car Class)
    • 方法区是一种规范
      • Java7是永久代
      • Java8是元空间
    • 实例变量存在堆内存中,和方法区无关

    Java栈

    栈管运行,堆管存储

    队列(FIFO)先进先出

    (FILO)先进后出

    Java栈保存:8种基本数据类型、对象的引用变量、实例方法

    Java中层面main方法是程序的入口,main方法会被保存到Java栈中,Java栈中层面叫做栈帧

    演示四

    方法递归调用,栈溢出

    1575794149620

    栈、堆、方法区的交互关系

    创建对象的过程Object obj = new Object()obj存储在Java中,实例对象数据存储在中,实例对象数据是由类模板创建出来的,类模板存储在方法区

    1575794350515

    堆结构

    逻辑上分

    • 新生代
      • 伊甸区
      • 幸存0区
      • 幸存1区
    • 老年代
    • 永久代(Java7)、元空间(Java8),方法区是一种规范,永久代或者是元空间是方法区的不同落地实现

    对于HotSpot虚拟机,很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” ,但严格本质上说两者不同,或者说使用永久代来实现方法区而已,永久代是方法区(相当于是一个接口interface)的一个实现,jdk1.7的版本中,已经将原本放在永久代的字符串常量池移走。

    1576051892566

    物理上则排除了永久代或者是元空间

    1576051849603

    证明堆结构

    package com.zbiti.jvm;
    
    public class HeapStructureDemo {
        public static void main(String[] args) {
            //返回 Java 虚拟机试图使用的最大内存量。
            long maxMemory = Runtime.getRuntime().maxMemory();
            //返回 Java 虚拟机中的内存总量。
            long totalMemory = Runtime.getRuntime().totalMemory();
            System.out.println("MAX_MEMORY = " + maxMemory + "(字节)、" + (maxMemory / (double) 1024 / 1024) + "MB");
            System.out.println("TOTAL_MEMORY = " + totalMemory + "(字节)、" + (totalMemory / (double) 1024 / 1024) + "MB");
        }
    }
    

    添加VM options :-XX:+PrintGCDetails

    1576052345574

    控制台输出

    可以看到输出了堆结构:新生代PSYoungGen、老年代ParOldGen、元空间Metaspace,那如何知道物理上堆结构只包含新生代和老年代呢

    新生代加上老年代的和38400K+87552K=125952K

    堆内存的默认初始化大小128974848字节128974848/1024=125952K,因此可知物理上堆结构只包含新生代和老年代

    1576053646764

    堆内存调优

    Java7

    1576054181737

    Java8

    1576054230377

    参数 说明
    -Xms 设置初始分配大小,默认为物理内存的1/64
    -Xmx 最大分配内存,默认为物理内存的1/4
    -XX:+PrintGCDetails 输出详细的GC处理日志

    修改堆参数,模拟堆溢出

    -Xms1024m -Xmx1024m -XX:+PrintGCDetails,设置堆初始值和最大值一样,避免峰值的低、高抖动

    package com.zbiti.jvm;
    
    import java.util.Random;
    
    public class HeapSpaceDemo {
        public static void main(String[] args) {
            String str = "com.zbiti.com";
            while(true){
                str+=str+new Random().nextInt(88888888)+new Random().nextInt(999999999);
            }
        }
    }
    

    1576200018621

    控制台

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

    1576199860861

    4大垃圾回收算法

    1576203461842

    JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC)

    • 普通GC(minor GC):只针对新生代区域的GC,指发生在新生代的垃圾收集动作,因为大多数Java对象存活率都不高,所以Minor GC非常频繁,一般回收速度也比较快。
    • 全局GC(major GC or Full GC):指发生在老年代的垃圾收集动作,出现了Major GC,经常会伴随至少一次的Minor GC(但并不是绝对的)。Major GC的速度一般要比Minor GC慢上10倍以上

    引用计数法

    1576293394802

    复制算法(Copying)

    使用在新生代

    1576293534032

    绿色:空闲的堆内存空间(新生代)

    红色:可回收的垃圾对象

    黄色:对象已经占用的堆内存空间

    蓝色:堆内存空间(老年代)

    1576293674987

    标记清除(Mark-Sweep)

    使用在老年代

    1576294271165

    1576294283136

    标记压缩(Mark-Compact)

    使用在老年代,比标记清除多一步压缩

    1576295775283

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    SQL server分离和附加数据库
    sql-server的添加数据库文件(日志数据)以及收缩数据库文件(日志数据)
    sql语句中的join用法(可视化解释)
    SQL语句(floor、ceiling和round以及left和right)
    怎样重新获得别人的信任-知识就是力量(思维导图)
    怎样让孩子爱上学习-知识就是力量(思维导图)
    洛谷-P1036 选数
    洛谷-P1028 数的计算
    洛谷-P1914 小书童——密码
    洛谷-P1598 垂直柱状图
  • 原文地址:https://www.cnblogs.com/lisingshen/p/12045523.html
Copyright © 2020-2023  润新知