请一定记得升级java虚拟机

简介: 我在做项目的时候,将自己所有涉及到的项目编译和运行JAVA版本都升级到了1.7。告诉其他人说:我们要好好利用JVM升级带来的免费性能福利。有人跟我说:其实服务器上是1.7啊,只是jenkins部署的时候用的1.6而已。我叹了口气,这个问题,要我详细讲的话,我可以讲上两天,以下是精简的部分。

对于吃货出身又需要保持体重的我,出门一定要带男票,因为这样就可以把见到的好吃的都买给他吃,就当是自己吃了[]偶尔做梦还是会梦到自己一个角落里偷吃东西,听到有脚步声,抬起头,大哭起来:“我饿了。” 然后就这样一直哭醒。

 微信图片_20220424184247.jpg


作为程序媛,对于程序的爱好,必须高于对吃的痴迷。虽然这对于吃货而言很难,但相比减肥都不是难事,因为我已经是一名腻害的程序媛了。


我在做项目的时候,将自己所有涉及到的项目编译和运行JAVA版本都升级到了1.7。告诉其他人说:我们要好好利用JVM升级带来的免费性能福利。有人跟我说:其实服务器上是1.7啊,只是jenkins部署的时候用的1.6而已。我叹了口气,这个问题,要我详细讲的话,我可以讲上两天,以下是精简的部分。


大家都知道,JAVA官网下载下来的包安装后里面有两个文件夹,一个是JDK(Java Development Kit),这是Java语言的软件开发工具包(SDK)。另一个是JRE(Java Runtime Environment),就是JAVA的运行时环境。如果JDK的文件夹是jdk1.7.XXX,那么相应的JRE的文件夹就是jre7。所以大家提到java版本的时候,有人习惯说java1.7,但还有人习惯说java7


JDK的文件夹里包含了JRE。所以正常服务器上只安装JDKWindows里会看到JRE文件夹里大多数的文件扩展名是DLL(Dynamic Link Library),这是动态链接库文件。在Windows™中,许多应用程序并不是一个完整的可执行文件,而是被分割成一些相对独立的DLL。一个应用程序可以使用多个DLL,一个DLL也可能被不同的应用程序使用。而Linux®里的JRE文件夹下因为是完整的可执行文件,所以文件数会少一些。而且Linux®一切皆文件,所以是没有扩展名的。


看了上面的两段,累了吧。我累的时候喜欢坐在路边长椅上一边喝酸奶(健康不长胖,耶!)一边看着如花的姑娘们从眼前走过。丰满的姑娘好似茶花,圆润可爱;浓妆的姑娘好似曼陀罗,美丽却有毒,让人想靠近又不敢靠太近;还有一种会让人联想到芍药的姑娘,秀丽的气质里藏不住更美的内在……


微信图片_20220424184352.jpg


言归正传啦,jenkins部署的时候一般包含两个步骤:一个是构建(build),还有一个是部署(deploy)。部署就是扔到实际运行服务器上。构建是先将所需要的资源按照指定的链接下载到本地,然后用JDK编译。那么用低版本的JDK进行编译有什么影响呢?


因为线上是能运行的,我们就刨去兼容问题不谈,只谈性能。


JAVA的编译期包括前端编译(将.java文件变成.class文件,.class文件就是字节码文件啦)提前编译(AOT ,ahead of time compiler,直接将.java文件编译成本地机器代码)运行期编译(JIT, just in time compiler,把字节码转变成机器码)。而jenkins部署的时候只做了前端编译。


我们常用的前端编译器:部署的时候用sunjavacBTW(by the way)javac是纯java写的,有兴趣的童鞋可以研究一下源码。开发的时候,由于笔者本人是eclipse的铁粉儿,用的是 eclipse JDT中的增量式编译器(ECJ, Eclipse Compiler for Java)。其实javac这类编译器对代码的运行效率击鼓没有任何优化(JDK1.3之后,javac-O优化参数就不再有意义了)。虚拟机设计团队把对性能的优化集中到了即时编译中,这样可以让那些不是javac产生的class文件也同样能享受到编译器优化带来的好处。


好吧,人家说的是对的,jenkins1.6编译对性能没有多大影响。毕竟我大乐视人才济济,不是随便一句话就可以忽悠人家的。但是javac做了许多针对编码过程的优化措施来改善程序员的编码风格和提高编码效率。相当多新生的java语法特性,都是靠编译器的语法糖(Syntactic Sugar,对功能没有影响,更方便程序员使用的语法)来实现,而不是依赖虚拟机的底层改进来支持,可以说,java中即时编译在运行期的优化过程对于程序运行来说更重要,而前端编译器在编译期的优化过程对于程序编码来说关系更加密切。


JAVA最初是通过解释器进行解释执行的,当虚拟机发现某人方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码”而将它们编译成本地机器码,并进行各种层次的优化,完成这个任务的编译器就是即时编译器。


微信图片_20220424184455.jpg



即时编译器也有不同的版本,比较常用的是HotSpot虚拟器的C1(clientcompiler用来获取更高的编译速度),C2(servercompiler获取更好的编译质量)编译器。它是解释器和编译器并存,保留解释器的原因是,加快启动时间,立即执行,当运行环境中内存资源限制较大时,解释器可以节约内存,解释器还可以作为激进优化的编译器的“逃生门”(称为逆优化Deoptimization,而编译器能把越来越多的代码编译成遍地代码后,获取更高的执行效率。HotSpot会根据自身版本和宿主机器的性能自动选择C1还是C2,用户也可以使用-client或者-server来自行决定。用户还可以使用-Xint强制虚拟机使用解释模式,也可以使用-Xcomp强制编译模式。


JDK设计团队几乎把代码的所有优化措施都集中在了即时编译器上,所以一般来说即时编译器产生的本地代码会比Javac产生的字节码更优秀。常用的优化技术有:公共子表达式消除,数组边界检查消除,方法内联,逃逸分析。有兴趣的童鞋可以自己研究一下,面试时很加分[胜利].


最开始还提到了提前编译。提前编译与即时编译的基本思想是相同的。在程序执行前生成Java方法的本地代码,以便在程序运行时直接使用本地代码。目的在于避免即时编译器的运行时性能消耗或内存消耗,或者避免解释程序的早期性能开销。


有人喜欢拿JAVAC/C++对比。早期的Java运行时所提供的性能级别远低于CC++。但是即时编译的出现使得现代的JIT编译器可以产生于CC++静态编译相当的应用程序性能。但是,JAVA在输出本地代码上还是有一些劣势。首先,因为即时编译器运行占用的是用户程序的运行时间,具有很大的时间压力,优化手段也严重受制于编译成本。其次,Java语言是动态的类型安全语言,需要由虚拟机来确保程序不会违反语言的寓意或者访问非结构化内存。第三,Java语言中虽然没有virtual关键字,但是使用虚方法(多态方法)的频率却远远大于CC++语言。这意味着运行时对方法接受者进行多态选择的频率要远远大于CC++语言,这加大的优化难度。第四,Java语言是可以动态扩展的语言,运行时加载新的类可能改变程序类型的继承关系,编译器不得不时刻注意并随着类型的变化而在运行时撤销或重新进行一些优化。第五,Java语言中对象的内存分配都是在堆上进行的,只有方法中的局部变量才能在栈上分配。但是Java语言的这些性能上的劣势都是为了换取开发效率上的优势,动态安全,动态扩展,垃圾回收这些特性都为Java语言的开发效率做出了很大的贡献。

 

小知识:聪明的你已经注意到了文章中Windows™和Linux®的角标。™是trade mark(商业标记)的缩写。表示此商标正在受理注册中,还没有取得商标证。®表示商标已经注册并取得了商标证。


建议:大家在用英文简写的时候把简写表示的意思都解释一下,因为一个简写有很多意思,读者们需要用很长的反射弧才能想明白。



 

相关文章
|
3月前
|
Java
【思维导图】JAVA网络编程思维升级:URL与URLConnection的逻辑梳理,助你一臂之力!
【思维导图】JAVA网络编程思维升级:URL与URLConnection的逻辑梳理,助你一臂之力!
56 1
|
19天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
36 2
|
25天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
21天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
11 0
|
2月前
|
存储 算法 Java
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
本文介绍了 JVM 的内存区域划分、类加载过程及垃圾回收机制。内存区域包括程序计数器、堆、栈和元数据区,每个区域存储不同类型的数据。类加载过程涉及加载、验证、准备、解析和初始化五个步骤。垃圾回收机制主要在堆内存进行,通过可达性分析识别垃圾对象,并采用标记-清除、复制和标记-整理等算法进行回收。此外,还介绍了 CMS 和 G1 等垃圾回收器的特点。
112 0
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
|
2月前
|
Oracle Java 关系型数据库
【颠覆性升级】JDK 22:超级构造器与区域锁,重塑Java编程的两大基石!
【9月更文挑战第6天】JDK 22的发布标志着Java编程语言在性能和灵活性方面迈出了重要的一步。超级构造器和区域锁这两大基石的引入,不仅简化了代码设计,提高了开发效率,还优化了垃圾收集器的性能,降低了应用延迟。这些改进不仅展示了Oracle在Java生态系统中的持续改进和创新精神,也为广大Java开发者提供了更多的可能性和便利。我们有理由相信,在未来的Java编程中,这些新特性将发挥越来越重要的作用,推动Java技术不断向前发展。
|
3月前
|
设计模式 算法 Java
【揭秘】如何巧妙运用Java模板方法模式,让你的代码优雅升级?
【8月更文挑战第30天】模板方法模式是一种行为型设计模式,它定义了算法的骨架并将某些步骤延迟到子类中,使子类能在不改变算法结构的情况下重定义特定步骤。此模式适用于具有共同结构但细节不同的场景,如角色升级系统。通过定义一个抽象类 `Character` 包含模板方法 `levelUp` 和抽象步骤方法,子类如 `Warrior` 和 `Mage` 可以实现具体逻辑。这种方式提供了良好的扩展性,确保算法结构不变,同时保持系统的稳定性和一致性,在数据处理和业务流程管理中广泛应用。
56 2
|
3月前
|
Java API Apache
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
|
3月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
3月前
|
Java 数据安全/隐私保护 Windows
【Azure Developer】使用Java代码启动Azure VM(虚拟机)
【Azure Developer】使用Java代码启动Azure VM(虚拟机)