网站建设zg886,seo关键词推广优化,网站后台不能上传,东莞市长安网站建设公司#x1f3ac;作者简介#xff1a;大家好#xff0c;我是小徐#x1f947;☁️博客首页#xff1a;CSDN主页小徐的博客#x1f304;每日一句#xff1a;好学而不勤非真好学者 #x1f4dc; 欢迎大家关注#xff01; ❤️ 我们知道#xff0c;想要把高级语言转变成计算… 作者简介大家好我是小徐☁️博客首页CSDN主页小徐的博客每日一句好学而不勤非真好学者 欢迎大家关注 ❤️ 我们知道想要把高级语言转变成计算机认识的机器语言有两种方式分别是编译和解释然Java转成机器语言的过程中有一个步骤是要编译成字节码但是这里的字节码并不能在机器上直接执行。
所以IM中内置了解释器(interpreter)在运行时对字节码进行解释翻译成机器码然后再执行。 解释器的执行方式是一边翻译一边执行因此执行效率很低。为了解决这样的低效问题HotSpo引入了JIT技术(Just-In-Time)。
有了JIT技术之后JM还是通过解释器进行解释执行。但是当IM发现某个方法或代码块运行时执行的特别频繁的时候就会认为这是“热点代码”(Hot Spot Code)。然后JIT会把部分“热点代码”翻译成本地机器相关的机器码并进行优化然后再把翻译后的机器码缓存起来以备下次使用。 扩展
HotSpot虚拟机中内置了两个JIT编译器:Client Complier和Server Complier分别用在客户端和服务端目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。 当 JM 执行代码时它并不立即开始编译代码(因为Java默认是解释执行的)。首先如果这段代码本身在将来只会被执行一次那么从本质上看编译就是在浪费精力。因为将代码翻译成 java 字节码相对于编译这段代码并执行代码来说要快很多。第二个原因是最优化当JVM 执行某一方法或遍历循环的次数越多就会更加了解代码结构那么JM 在编译代码的时候就做出相应的优化。
在机器上执行java -version命令就可以看到自己安装的JDK中JIT是哪种模式: 上图是我的机器上安装的jdk1.8可以看到他是Server Compile但是需要说明的是无论是Client Complier还是Server Complier解释器与编译器的搭配使用方式都是混合模式即上图中的mixed mode。
热点检测
上面我们说过要想触发JIT首先需要识别出热点代码。目目前主要的热点代码识别方式是热点探测(Hot Spot Detection)有以下两种:
基于采样的方式探测(Sample Based Hot Spot Detection):周期性检测各个线程的栈顶发现某个方法经常出现在栈顶就认为是热点方法。好处就是简单缺点就是无法精确确认一个方法的热度。容易受线程阻塞或别的原因干扰热点探测。基于计数器的热点探测(Counter Based Hot Spot Detection)。采用这种方法的虚拟机会为每个方法甚至是代码块建立计数器统计方法的执行次数某个方法超过阀值就认为是热点方法触发JIT编译。
在HotSpot虚拟机中使用的是第二种--基于计数器的热点探测方法因此它为每个方法准备了两个计数器:方法调用计数器和回边计数器。
方法计数器。顾名思义就是记录一个方法被调用次数的计数器。
回边计数器。是记录方法中的for或者while的运行次数的计数器
编译优化
前面提到过JIT除了具有缓存的功能外还会对代码做各种优化。说到这里不得不佩服HotSpot的开发者他们在川T中对于代码优化真的算是面面俱到了。 主要的优化有:逃逸分析、锁消除、 锁膨胀、方法内联、!类型检测消除、空值检查消除、公共子表达式消除。接下来挑几个重点的介绍一下。
锁消除
在动态编译同步块的时候川T编译器可以借助逃逸分析来判断同步块所使用的锁对象是否只能够被一个线程访问而没有被发布到其他线程。 如果同步块所使用的锁对象通过这种分析被证实只能够被一个线程访问那么JIT编译器在编译这个同步块的时候就会取消对这部分代码的同步。这个取消同步的过程就叫同步省略也叫锁消除。
JIT优化可能带来的问题
大家理解了JIT编译的原理之后其实可以知道JIT优化是在运行期进行的并且也不是Java进程刚一启动就能优化的是需要先执行一段时间的因为他需要先知道哪些是热点代码。 所以在JIT优化开始之前我们的所有请求都是要经过解释执行的这个过程就会相对慢一些。 而且如果你们的应用的请求量比较大的的话这种问题就会更加明显在应用启动过程中会有大量的请求过来这就会导致解释器持续的在努力工作。
一旦解释器对CPU资源占用比较大的话就会间接的导致CPU、LOAD等飙高导致应用的性能进一步下降。这也是为什么很多应用在发布过程中会出现刚刚重启好的应用会发生大量的超时问题了
而随着请求的不断增多JIT优化就会被触发这就是使得后续的热点请求的执行可能就不需要在通过解释执行了直接运行川T优化后缓存的机器码就行了。
如何解决
那么怎么解决这样的问题呢?
主要有两种思路:
1提升JIT优化的效率2降低瞬时请求量
在提升JIT优化效率的设计上大家可以了解-下阿里研发的JDK--Dragonwell。
这个相比OpenJDK提供了一些专有特性其中一项叫做JwarmUp的技术就是解决J优化效率的问题的。
这个技术主要是通过记录Java应用上一次运行时候的编译信息到文件中在下次应用启动时读取该文件从而在流量进来之前提前完成类的加载、初始化和方法编译从而跳过解释阶段直接执行编译好的机器码。
除了针对JDK做优化之外还可以采用另外一种方式来解决这个问题那就是做预热。
很多人都听说过缓存预热其实思想是类似的。
就是说在应用刚刚启动的时候通过调节负载均衡不要很快的把大流量分发给他而是先分给他一小部分流量通过这部分流量来触发ЛT优化等优化好了之后再把流量调大。