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