java-运行

作者: go_2021 | 来源:发表于2022-02-05 15:44 被阅读0次

    欲望就像拥塞控制,控制不住,那就只能重新再来。

    1.用到后
    5种:main所在类,new,反射,子类,静态属性或方法。
    
    2.加载器

    启动(JAVA_HOME/lib),扩展(JAVA_HOME/lib/ext),应用(CLASS_PATH)
    默认实现

    • 惰性加载(用到才加载)
    • 传递性(a用到b,那加载b就用a的加载器)
      jndi(配置在文件,开发运维解耦;根包定义接口,实现在各厂商。)
      接口在JAVA_HOME/lib,而spi接口的实现是在CLASS_PATH下,就用到了ThreadContextClassLoader来打破传递性。
    • 双亲委派 (启动- 扩展- 应用 顺序来加载,不会重复加载)
      打破双亲委派自定义加载器如tomcat,实现隔离。
      通过重写加载器,还可以实现热加载(jsp刷新不用重启。热部署:自动打包重启)。
    3.后端编译器(jit)

    两种模式:

    • client compile
    • server compile
      优化深入,关注全局

    2种检测方法,达到次数编译成机器码提高执行效率:

    • 回边计数
      执行到}计数,栈上替换。
    • 方法计数
      针对方法。

    常见的优化方法:
    方法内联数组边界消除逃逸分析子表达式消除

    4.初始化顺序
    5.GC
    过程
    • new -> 新生区
    • 新生区满了 -> 幸存区1
    • 新生区又满了 -> 幸存区2
    • 年满15-> 老年区
    常用GC计数

    引用计数(python php 循环引用),可达性分析(java c#)

    GC root

     栈 方法区 本地方法区

    4中引用

    (不GC) (ooMGC) (直接GC) (直接GC 存放队列,可回收前做一些事情)

    回收器
    • serial(单) parNew(多)
    • parallel(吞度量1.7 1.8)
    • G1(兼并 1.9,新老物理内存合并)
    • cms
    回收器CMS(并发标记清除)
    • 清除过程
      单线程标记
      简单的对gcroot直接引用的对象进行记录,期间会STW。
      并发标记
       对gcroot进行所有对象的扫描,耗时最长但是不会STW,期间标记之后的对象状态可能会发生变化,所以需要重新标记。
       标记是用的 三色标记法增量更新三色标记法是把对象分为白灰黑,3种颜色,开始都是白色,被引用标记为灰色,灰色上的引用都标记完,灰色变黑色,最后只留白色和黑色,白色被回收。
       期间不停止用户线程,所以会有2种问题,该回收的没回收,不该回收的回收了。针对第一个问题就是浮动垃圾问题,下一次回收就可以了。第二个问题,就比较严重了,产生第二个问题有两个必要条件:1.节点与灰色的引用被删。2.节点又与黑色节点创建了引用。
      增量更新就是记录期间添加的记录,在从黑色节点重新扫描,打破了第二点。
      原始快照是G1用的方法,会对被删除的引用记录,走快照的结果,打破了第一点。
      重新标记
      对上一步标记的对象进行修正。期间会STW。
      并发清理
    • 缺点:
      CPU资源问题:CPU使用较强,容易抢多服务CPU资源。
      浮动垃圾问题:产生的浮动垃圾无法处理,如在并发标记与并发阶段中又产生垃圾那么只能等到下次GC再进行处理。
      空间碎片问题:由于使用的标记-清除算法,因此在回收结束的时候会产生空间碎片问题,但是可以通过参数设置来解决,不过会消耗点性能。
      concurrent mode failure问题:在并发标记或并发清理阶段的时候,如果又触发了垃圾回收,但是本次垃圾回收又没进行完,那么则会触发concurrent mode failure,这时候则会进入到单线程收集,先stop the world,随后使用上文提到的serial old垃圾回收器来进行回收。
    • 相关参数
      XX:+UseCMSCompactAtFullCollection: 可以让jvm在执行完标记清除后再做整理,解决上文提到的空间碎片问题,类似使用标记-整理算法。
      -XX:ConcGCThreads:设置GC的时候并发线程数
      -XX:CMSInitiatingOccupancyFraction: 老年大使用百分比达到该值的时候会触发垃圾回收(默认是92)
      -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW。
      -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW。
    • 暂停安全
      循环末尾,方法末尾,抛异常。
    回收算法
    • 标记清理标记然后清理。(老年代cms+g1)
    • 标记复制标记完,剩下的进行复制,原来内存直接清除。(新生代)
    • 标记整理在标记清理的基础上进行整理。(老年代)
    内存泄漏

    ThreadLocal的value手动释放。
    单例,方法区引用的。
    io资源,lock,close释放。

    GC测试

    打印GC信息:-XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC

    byte[] placeHolder = new byte[64 * 1024 * 1024];
    //placeHolder = null;
    System.gc();
    
    //第2行注释:[Full GC (System.gc())  67386K->67199K(125952K), 0.0151228 secs]
    //第2行不注释:[Full GC (System.gc())  67370K->1662K(125952K), 0.0065968 secs]
    
    byte[] placeHolder = new byte[64 * 1024 * 1024];
    TestGC testGC = new TestGC(placeHolder);
    placeHolder = null;
    //testGC = null;
    System.gc();
    
    //第4行注释:[Full GC (System.gc())  67386K->67199K(125952K), 0.0151228 secs]
    //第4行不注释:[Full GC (System.gc())  67370K->1662K(125952K), 0.0065968 secs]
    
    Object a= new Object();  b = new B(a); a=null; //Obect内存并不能释放
    

    相关文章

      网友评论

        本文标题:java-运行

        本文链接:https://www.haomeiwen.com/subject/rgzdkrtx.html