JVM-垃圾回收机制-GC/类加载器和双亲委派机制、JVM内存区域、垃圾回收算法、JVM调优原则

  • ?Java如何实现的跨平台的?
    • ◆ 因JVM机制,JVM作用:是将 Class字节码的文件,通过ClassLoader(类加载器),
    • ◆ 加载到RuntimeDataAreas(指’运行时内存’),
    • ◆ 运行时内存又分:方法区,堆区,栈区,线程,程序计数器,本地方法接口(主要供给Java操作底层的C语言的实现),一一构成的;
    • ◆ 运行时内存的数据,会通过程序的一个执行引擎[执行引擎中最重要的是一个垃圾回收器],跟操作系统交集。
    • ?类从编译到执行的过程?
    • ‣ 编译器(IDEA)将Dog.java 源文件编译曾Dog.class 字节码文件.
    • ‣ ClassLoader(类加载器)将字节码文件转换为JVM中的Class对象.
    • ‣ JVM使用Class对象实例化出Dog对象.
    • ?描述一下类加载和双亲委派机制?[JVM内机制]
    • ➣ 自定义类加载器➩’挂载关系’➩ 系统/应用类加载器(Application_加载器)➩’委托关系’➩扩展加载器(Ext_加载器)➩’委托关系’➩ 启动类/根加载器(lib_加载/ClassLoader_类加载器)
    • ⬆加载用户指定目录下的Class ➩ ⬆classPath路径下指定,如未设置则为应用程序当前路径 ➩ ⬆%JAVA_HOME%/jre/lib/ext路径下的jar包 ➩ ⬆%JAVA_HOME%/lib路径下的jar包
    • ➣ 1-挂载 ➩ 2-委托 ➩ 3-委托 ⬇︎
    • ▲自定义类加载器路径下找不到抛出ClassNotFound异常 ⬅︎ AppClassLoader加载路径下未找到交由自定义加载器去加载 ⬅︎ ExtClassLoader加载器路径下未找到交由AppClassLoader去加载 ⬅︎ BootStrap加载路径下未找到目标Class交由ExtClassLoader去加载 ⬆
    • ❖ 编写自定义类加载器
* @describe 自定义类加载器
 * @requirement 具体需求
 */
public class CustomizeClassLoader extends ClassLoader{

    private String path;
    private String classLoaderName;

    public CustomizeClassLoader() {
    }

    public CustomizeClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }

    /**
     * 自定义一个类加载器
     * 完成从根下某个目录加载class文件
     * @param name
     * @return
     */
    private byte[] loadClassData(String name){
        name = path + name + ".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try{
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i=in.read())!=-1){ //一直监听
                out.write(i);
            }
        }catch (Exception ignored){

        }finally {
            try {
                assert in != null;
                in.close();
                assert out != null;
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        assert out != null;
        return out.toByteArray();
    }
}
class CustomizeClassLoaderTest{
    public static void main(String[] args) throws Exception {
        // 打印类加载器文件目录
        out.println(System.getProperty("sun.boot.class.path")+"-------");
        out.println(System.getProperty("java.ext.dirs")+"-------");
        out.println(System.getProperty("java.class.path")+"-------");

        //使用自定义类加载器加载Dog.class
        CustomizeClassLoader classLoader = new CustomizeClassLoader("/Spring-Learn/java-basics/jdk-jvm/src/main/resources/file/","CustomizeClassLoader");
          Class<?>  cl = classLoader.loadClass("Dog");
          Object obj = cl.newInstance();

          // 双亲委派机制
          out.println(obj+"-------");
          out.println(obj.getClass().getClassLoader()+"-------自定加载器");
          out.println(obj.getClass().getClassLoader().getParent()+"-------系统/应用类加载");
          out.println(obj.getClass().getClassLoader().getParent().getParent()+"-------扩展加载器/平台加载器");
    }
}

 *
 *  ?JVM内存区域?
 *   ◆ 方法区(元数据)、Java堆(包含:运行时字符串常量池/New对象)、Java栈、本地方法栈、程序计数器/PC寄存器、--五大内存区域
 *    ▸ 类加载器 ➟ 方法区(元数据)、① {Method Area、}
 *    ▸ 垃圾回收器/系统 ➟ 方法区(元数据)、Java堆(包含:运行时字符串常量池)、② {Method Area、Java Heap、}
 *    ▸ 执行引擎 ➟ 方法区(元数据)、Java堆、Java栈、程序计数器/PC寄存器、④ {Method Area、Java Heap、Java Tack、Program Counter Register、}
 *
 *    ❖ 当前线程私有的(Thread-private)部分,独立存储:
 *          ▴ 程序计数器/PC寄存器:它记录类线程执行的字节码的行号,在分支,循环,跳转,异常,线程恢复等都依赖这个计数器。
 *          ▴ Java栈:它创建栈帧.栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧里面包括(局部变量表、操作数帧、动态链接、方法出口、方法栈等)。
 *          ▴ 本地方法栈: > 先解释下什么是本地方法,jvm中的本地方法是指方法的修饰符是带有'Native 关键字的',但方法体不是用Java语言编写的(主要应用于,调用底层C语言编写所应用的)。
 *
     ✮'Java栈里的局部变量'中的某个变量,New出来的对象,是要'引用到Java堆中的某个内存地址的',隐式操作关系的(示:地址引用、值引用 等关系)。

 * @describe 栈中局部变量,引用到Java堆中的值引用关系
 * @requirement resources ☞ 资源包中有逻辑图解释
 */
public class LocalVariableCiteJavaHeapMemoryAddressTest {
    private static void m2(Student stu){
        stu.age++;

    }
    private static void m1(int i){
       i += 1;
    }
    public static void main(String[] args) {
        int i = 10;
        m1(i);
        out.println(i); //? 值:10
        Student stu = new Student();
        stu.age=i;
        m2(stu); //传参数是引用变量
        out.println(stu.age);//?值:11
    }
}
@Data
class Student{
    int age;
}
 *
 *  ?垃圾回收算法??
 *  ◆ 引用计数法(存在,循环引用问题)
 *  ◆ 可达性分析法/根搜索法
 *  ◆ 标记清除算法(Mark-Sweep)-(存在内存碎片问题)
 *  ◆ 复制算法(Copying)-(存在内存利用率低问题)
 *  ◆ 标记整理算法(Mark-Compact)-(存在算法相对复杂问题)
 *  ◆ 分代回收法(新生代(minorGC)1/3堆[Eden区占比率(8/10)、from区占比率(1/10)、to区占比率(1/10)]空间,老年代(MaxGC)2/3堆空间)、老年代GC会触发FullGC
 *    ◼ ??新生代什么条件下会进入老年代?
 *       ▴ 当新生代中的三个区被New对象/引用对象,占满没有内存空间时;
 *       ▴ New/引用对象,每次存活一次都会给它默认的age+1,当值为15时,将会转移到老年区;
 *       ▴ 因新申请大内存空间大于新生代的总和情况下;
 *
 *    ◼??老年代GC会触发FullGC(整个堆GC)机制,触发条件是什么??
 *        ▴ 老年代空间不足
 *        ▴ 永久代空间不足
 *        ▴ 新生代(minorGC)晋升到老年队,但老年代的空间不足时
 *        ▴ 指令操作, System.gc(); --显式调用方式
 *
 *    ◼??触发了,FullGC(整个堆GC)机制,不好一面是什么?
 *       ▵ 它会有一个不好的动作,动作叫做:'top teh world stw.'(线程都停止了)。
 *
 *    ◼ ? ︎? ? 垃圾回收器,对于新生代和老年代不同的回收器组合??
 *          ➢ 新生代[垃圾回收器]:Serial、ParNew、Parallel Scavenge、 (串行化、标准新的、并行清除、)
 *          ➢ 老年代[垃圾回收器]:CMS、Serial Old、 Parallel Old、(内容管理、串行化老年代的、并行老年代的、)
 *          ➣ 其他[垃圾回收器]: ⬇︎
 *                   ▴ Eplison (用途,调试使用)
 *                   ▴ G1 (JDK_1.9 版本引入)
 *                   ▴ ZGC (JDK_14 版本引入)
 *
 *    ◆ 垃圾回收器-CMS,执行流程:?
 *      ➣ 初始标记: stop-the-world,标记GCRoots直接关联的对象,
 *      ➣ 并发标记: 并发追溯标记,程序不会停顿,
 *      ➣ 重新标记: 暂停虚拟机,扫描CMS堆中的剩余对象,
 *      ➣ 并发清理: 清理垃圾对象,程序不会停顿,
 *      ➣ 并发重置: 重置CMS收集器的数据结构。
 *
 *    ◆ 垃圾回收器-G1 ? ?
 *      ➣ G1 将整个JVM内存分为多个大小相等的 Region(范围),新生代和老年代不再物理隔离。存在逻辑上的分代的概念。
 *      ➣ G1 是 Java_9 以后,默认垃圾回收器,
 *      ➣ G1 整体上使用的是'标记整理算法(Mark-Compact)-(存在算法相对复杂问题)','局部使用复制算法(Copying)-(存在内存利用率低问题)',
 *      ➣ G1 的每个 Region(范围) 大小在 1-32M 之间,
 *         --可以通过 -XX:G1 HeapRegionSize = n; 指定区大小。
 *      ➣ G1 总的 Region(范围)个数最大可以存在 2048个,即 heap 最大能够达到32M*2048=64G,
 *      ➣ 0.5 < obj < 1,那么放到old区,old标记为H1 < obj < n,连续的n个region,作为H。
 *      ➣ Eden Space、Survivor Space、Old Generation、Humongous、(伊甸园、幸存者区、老年代、大型对象(Humongous )是大于G1中region大小50%的对象)。
 *
 *       ◆ 垃圾回收器-G1,执行流程: ? ?
 *        ➤ 初始标记: 只标记GCRoots能直接关联的对象,
 *        ➤ Root Region Scanning:扫表整个old的Region,
 *        ➤ 并发标记:并发追溯标记,进行GCRootsTracing的过程,
 *        ➤ 最总标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象,
 *        ➤ 清理回收:根据时间来进行价值最大化的回收,重置rest。
 *         ☞ -XX:+UserG1GC:设置使用G1垃圾回收器,
 *         ☞ -XX:MaxGCPauseMillis=n:最大GC停顿时间,毫秒值,
 *         ☞ -XX:ImitatingHeapOccpuancyPercent=n:当堆空间占用到 N 兆(M)时就触发GC(默认:45M),
 *         ☞ -XX:GoncGCThreads=n:并发GC使用的线程数,
 *         ☞ -XX:G1ReserverPercent=n:设置作为空闲空间的预留内存百分比(10%).
 *
 *    ✮ 垃圾回收器 CMS 与 G1 有什么区别呢???
 *      ‣ 1-G1,不会有碎片,它基于标记整理算法(Mark-Compact)的、'年轻代用的复制算法、老年代用的标记整理算法'-这两个算法的特点都是,没有内存碎片的;
 *      ‣ 2-G1,显著的优点:能够精确的控制,最大时间停顿GC的毫秒值,在不牺牲吞吐量的情况下,降低停顿时间。

点击-源代码地址:CodeChina

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值