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

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

我在做项目的时候,将自己所有涉及到的项目编译和运行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。所以正常服务器上只安装JDK。Windows™里会看到JRE文件夹里大多数的文件扩展名是DLL(Dynamic Link Library),这是动态链接库文件。在Windows™中,许多应用程序并不是一个完整的可执行文件,而是被分割成一些相对独立的DLL。一个应用程序可以使用多个DLL,一个DLL也可能被不同的应用程序使用。而Linux®里的JRE文件夹下因为是完整的可执行文件,所以文件数会少一些。而且Linux®一切皆文件,所以是没有扩展名的。

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

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

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

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

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

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

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

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

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

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

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

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

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

请一定记得升级java虚拟机的更多相关文章

  1. 实战Java虚拟机之三“G1的新生代GC”

    今天开始实战Java虚拟机之三:“G1的新生代GC”. 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟机之三“G1的新生代GC” 实 ...

  2. 实战Java虚拟机之二“虚拟机的工作模式”

    今天开始实战Java虚拟机之二:“虚拟机的工作模式”. 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟机之三“G1的新生代GC” 实 ...

  3. Java虚拟机垃圾回收(三) 7种垃圾收集器

    Java虚拟机垃圾回收(三) 7种垃圾收集器 主要特点 应用场景 设置参数 基本运行原理 在<Java虚拟机垃圾回收(一) 基础>中了解到如何判断对象是存活还是已经死亡?在<Java ...

  4. Java虚拟机垃圾回收(三): 7种垃圾收集器(转载)

    1.垃圾收集器概述 垃圾收集器是垃圾回收算法(标记-清除算法.复制算法.标记-整理算法.火车算法)的具体实现,不同商家.不同版本的JVM所提供的垃圾收集器可能会有很在差别,本文主要介绍HotSpot虚 ...

  5. 《Java虚拟机原理图解》4.JVM机器指令集

    0. 前言 Java虚拟机和真实的计算机一样,执行的都是二进制的机器码:而我们将.java 源码编译成.class 文件,class文件便是Java虚拟机可以认识的二进制机器码,Java可以识别cla ...

  6. 《java虚拟机》汇总所有关键要点

    一  .java虚拟机底层结构详解 我们知道,一个JVM实例的行为不光是它自己的事,还涉及到它的子系统.存储区域.数据类型和指令这些部分,它们描述了JVM的一个抽象的内部体系结构,其目的不光规定实现J ...

  7. 《深入理解Java虚拟机》第2版挖的坑终于在第3版中被R大填平了

    这是why技术的第34篇原创文章 本周还是在家办公的一周,上面的图就是我在家的工位,和上周<Dubbo Cluster集群那点你不知道的事>这篇文章里面的第一张图片比起来,升级了显示器支撑 ...

  8. 《深入理解Java虚拟机》第 3 版里面到底多了哪些知识点?本文竟然得到了本书作者的认可!

    这是why的第 47 篇原创文章 荒腔走板 大家好,我是 why.老规矩,先是简短的荒腔走板聊聊生活. 上面的图是前几天拍的,那天晚上下班后,刚刚走进小区就看到了这一轮弯月和旁边那一颗特别特别亮的星星 ...

  9. 《深入理解Java虚拟机》类文件结构

    上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...

随机推荐

  1. 由Spring框架中的单例模式想到的

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例 注:Spring源码的版本4.3.4 Spring依赖注入Bean实例默认 ...

  2. Struts系列笔记(6)---action接收请求参数

    action接收请求参数 在web开发中,去接收请求参数来获得表单信息非常的常见,自己也总结整理了有关Struts2通过action接收请求参数的几种方法. Struts2 提供三种数据封装的方式: ...

  3. 负笈前行--DPDK代码风格

    每个公司都会有自己代码风格或者编程规范,都旨在防范编程语言的一些陷阱或者提高代码效率,还有就是保持一致编码风格来提高代码可读性,方便code review: 或者说代码的一种美学,比如python也就 ...

  4. php常见面试问题

    1. 如果没有开启cookies,session如何工作? PHP中的sessions通常会使用cookies的方法.但是如果没有cookies(浏览器禁用cookies),PHP sessions也 ...

  5. java学习之路

    先来说一说我和it之间的不解之缘.准确来说,我接触it是从大二是我买的第一个手机开始的(国产的,展讯平台,能够运行mrp虚拟机),那时候还没有智能手机,或者说还不够普及,总之就是买不起.一次偶然的机会 ...

  6. 连连看的原生JS实现V2

    对上一次的连连看程序进行了一点修改: var llk = function () { this.ReStart(); } llk.prototype = { Init: function () { / ...

  7. Winfrom 程序打包及安装

    前言 近期被公司外派到驻空调厂的项目组,支援一个TCP相关的程序对接.主要是做智能门禁系统,然后主要是统计出实时的进出人数. 我这边能作为服务端,门禁设备作为客户端,整个流程并不算复杂,根据协议来写, ...

  8. Android 退出多Activity的application的方式

    在开发过程中,我们常常需要一个退出功能,来退出该应用的所有Activity.下面,我们列举一些退出应用的几种方式.以下用的源码点击查看源码地址 欢迎star,欢迎fork 利用ActivityCont ...

  9. ABP Zero 多租户管理

    ABPZero - 多租户管理 启用多租户 ASP.NET Boilerplate和module-zero可以运行多租户或单租户模式.多租户默认为禁用.我们可以在我们的模块PreInitialize方 ...

  10. 类比Spring框架来实现OC中的依赖注入

    如果你之前使用过JavaEE开发中的Spring框架的话,那么你一定对依赖注入并不陌生.依赖注入(DI: Dependency Injection)是控制反转(IoC: Inversion of Co ...