Java术语

澳门新葡萄京所有网站 1

Java的工作方式

 澳门新葡萄京所有网站 2澳门新葡萄京所有网站 3

你要做的事情就是会编写源代码

 

英文原义:Just-In-Time

前言

这两天重温了周志明的《深入理解Java虚拟机》第2版,发现第11章第4节关于
Java 编译器的内容写得太棒了~本文完全摘自《深入理解Java虚拟机》第2版 0_o

Java的程序结构

澳门新葡萄京所有网站 4

类存于源文件里面

方法存在类中

语句存于方法中

中文释义:Java语言编译器

Java 与 C/C++ 编译器

大多数程序员都认为C/C++会比Java语言快,甚至觉得从Java语言诞生以来“执行速度缓慢”的帽子就应当扣在它的头顶,这种观点的出现是由于Java刚出现的时候即时编译技术还不成熟,主要靠解释器执行的Java语言性能确实比较低下。但目前即时编译技术已经十分成熟,Java语言有可能在速度上与C/C++一争高下吗?要想知道这个问题的答案,让我们从两者的编译器谈起。

Java与C/C++的编译器对比,实际上代表了最经典的即时编译器静态编译器澳门新葡萄京所有网站 ,的对比,很大程度上也决定了Java与C/C++的性能对比结果,因为无论是C/C++还是Java代码,最终编译之后被机器执行的都是本地机器码,哪种语言的性能更高,除了它们自身的API库实现地好坏之外,其余的比较就成了一场拼编译器的游戏。当然,这种比较也是剔除了开发效率的片面对比,语言孰优孰劣、谁快谁慢的问题都是很难有结果的争论,下面我们就回到正题,看看这两种语言的编译器各有何优势。

剖析类

当Java虚拟机启动执行时,它会寻找你在命令列中所指定的类,然后它会锁定像下面这样一个特定的方法:

public static void main(String[] args){
    //code
}

接着java虚拟机就会执行main方法在花括号间的函数所有指令。每个Java程序最少都会有一个类以及一个main()。每个应用程序只有一个main()函数

 

编写带有main()的类

在Java中的所有东西都会属于某个类。源文件为.java,编译之后成为新的类文件.class
,真正被执行的是类。

总之main()就是程序的起点。不管你的程序有多大(不管有多少个类)一定会有一个main()来作为程序的起点。

 

QAQ

为何所有的东西都得包含在类中?

因为Java是面对对象的语言,它不像以前的程序语言那样。类是对象的蓝图,而Java中的绝大多是东西都是对象。

每个类都需要加上一个main()吗?
一个程序只要一个main来作为运行。

其他语言可以用整数类型(0代表)来做判断,Java里面也可以么?

不行,Java中的integer与boolean两种类型并不相容。

注  解:它允许实时地将Java解释型程序自动编译成本机机器语言,以使程序执行的速度更快。有些JVM包含JIT编译器。

Java 编译器“劣势”的原因

Java虚拟机的即时编译器与C/C++的静态优化编译器相比,可能会由于下列原因,而导致输出的本地代码有一些劣势(下面列举的也包括一些虚拟机执行子系统的性能劣势):

第一,因为即时编译器运行占用的是用户程序的运行时间,具有很大的时间压力,它能提供的优化手段也严重受制于编译成本。如果编译速度达不到要求,那用户将在启动程序或程序的某部分察觉到重大延迟,这点使得即时编译器不敢随便引入大规模的优化技术,而编译的时间成本在静态优化编译器中并不是主要的关注点。

第二,Java语言是动态的类型安全语言,这就意味着需要由虚拟机来确保程序不会违反语言语义或访问非结构化内存。从实现层面上看,这就意味着虚拟机必须频繁地进行动态检查,如实例方法访问时检查空指针、数组元素访问时检查上下界范围、类型转换时检查继承关系等。对于这类程序代码没有明确写出的检查行为,尽管编译器会努力进行优化,但是总体上仍然要消耗不少的运行时间。

第三,Java语言中虽然没有virtual关键字,但是使用虚方法的频率却远远大于C/C++语言,这意味着运行时对方法接收者进行多态选择的频率要远远大于C/C++语言,也意味着即时编译器在进行一些优化(如方法内联)时的难度要远远大于C/C++的静态优化编译器。

第四,Java语言是可以动态扩展的语言,运行时加载新的类可能改变程序类型的继承关系,这使得很多全局的优化难以进行,因为编译器无法看清程序的全貌,许多全局的优化都只能以激进优化的方式来完成,编译器不得不时刻注意并随着类型的变化而在运行时撤销或重新进行一些优化。

第五,Java语言的对象内存是在堆上,只有方法的局部变量才能在栈上分配,而C/C++的对象则有多重内存分配方式,既可能在堆上分配,又可能在栈上分配,如果可以在栈上分配线程私有的对象,将减轻内存回收的压力。另外,C/C++中主要由用户用程序代码来回收分配的内存,这就不存在无用对象筛选的过程,因此效率上(仅是运行效率,排除开发效率)也比Java的垃圾收集机制要高。

专家术语学习机

package chapter1;

public class PhraseOMatic {

    public static void main(String[] args) {
        String[] wordListOne = { "24/7", "multiTier", "30,000 foot", "B-to-B",
                "win-win", "front-end", "web-based", "parvasive", "smart",
                "sixsigma", "critical-path", "dymatic" };

        String[] wordListTwo = { "empowered", "sticky", "value-added",
                "oriented", "centric", "distributed", "clustered", "branded",
                "outside-the-box", "positioned", "networked", "focused",
                "leveraged", "aligned", "targeted", "shared", "cooperative",
                "accelerated" };

        String[] wordListThree = { "process", "tippingpoint", "solution",
                "architecture", "core competency", "strategy", "mindshare",
                "portal", "space", "vision", "paradigm", "mission" };
        int oneLength = wordListOne.length;
        int twoLength = wordListTwo.length;
        int threeLength = wordListThree.length;

        int rand1 = (int) (Math.random() * oneLength);
        int rand2 = (int) (Math.random() * twoLength);
        int rand3 = (int) (Math.random() * threeLength);

        String phrase = wordListOne[rand1] + " " + wordListTwo[rand2] + " "
                + wordListThree[rand3];

        System.out.println("What we need is a " + phrase);
    }

}

random()方法返回介于0到1之间的值。

 

编译器与JVM谁比较重要?

编译器就是把源码编译成二进制代码,即字节码,并检查语法错误,程序员不可能自己去写二进制的代码,所以需要编译器。Java是个强类型的语言,这代表编译器不能容许变量保存类型的数据,这是很关键的类型安全性功能,编译器能让大部分的错误在到你那边之前就被抓到,有些数据类型的错误会在运行时发生,但这也是为了要容许动态绑定这样的功能。Java可以在执行期引起连程序员也没有预期会碰到的类型,所以我编译器保留一些运用性,编译器的工作就是确保铁定不能跑的东西不会过关。

但是如果没有JVM Java程序就无法启动

 

Java 编译器的“优势”

上面所了一堆Java语言在性能上的劣势,这些都是为了换取「开发效率」上的优势而付出的代价,动态安全、动态扩展、垃圾回收这些“拖后腿”的特性,都为Java语言的开发效率做出了很大贡献。

何况,还有许多优化是Java的即时编译器能做,而C/C++的静态优化编译器不能做或者不好做的。例如,在C/C++中,别名分析(Alias
Analysis)的难度就要远远高于Java。Java的类型安全保证了在类似如下代码中,只要ClassA和ClassB没有继承关系,那对象objA和objB就绝不可能是同一个对象,即不会是同一块内存两个不同别名。

void foo(ClassA objA, ClassB objB) {
    objA.x = 123;
    objB.y = 456;
    // 只要objB.y不是objA.x的别名,下面就可以保证输出为123
    print(objA.x);
}

确定了objA和objB并非对方的别名后,许多与数据依赖相关的优化才可以进行(重排序、变量替换)。具体到这个例子中,就是无需担心objB.y与objA.x指向同一块内存,这样就可以安全地确定打印语句中的objA.x为123。

Java编译器另外一个红利是由它的动态性所带来的,由于C/C++编译器所有优化都在编译期完成,以运行期性能监控为基础的优化措施它都无法进行,如:

  1. 调用频率预测:Call Frequency Prediction
  2. 分支频率预测:Branch Frequency Prediction
  3. 裁剪未被选择的分支:UNtaken Branch Pruning

这些都是Java语言独有的性能优势。

总结

随着Java
JIT编译技术的发展,Java的运行速度已经足够快。Java能够在运行时动态加载类(可以从zip包、网络、运行时计算、其他文件生成),C/C++则完全做不到这一点。总的来说,Java的动态安全、动态扩展、垃圾回收等特性,使得开发效率很高,并且足够灵活;同时随着编译技术的不断发展,性能的劣势正在逐渐减小。