[看书笔记]《深入java虚拟机》——java体系结构(一)

时间:2021-11-01 09:36:28

java的这种适合网络环境的能力是由其体系结构决定的,它可以保证安全的、健壮的且和平台无关的程序通过网络传播,在很多不同的计算机和设备上运行。

体系结构包括四个独立但相关的技术:
- java程序设计语言
- java class文件
- java应用编程接口(API)
- java虚拟机

用java编程语言编写源代码,把它编译成java class文件,然后再在java虚拟机中运行class文件。当程序运行的时候,它通过调用class文件中实现了java API的方法来满足程序的java API调用。

java虚拟机和java API组成了一个“平台”,所有java程序都在这上面编译。被称为“java运行时系统”,或者“java平台”。

----------------java虚拟机:
java面向网络的核心就是java虚拟机,它支持java面向网络体系结构三大支柱的所有方面:平台无关性、安全性、网络移动性。
java虚拟机上一台抽象的计算机,其规范定义了每个java虚拟机都必须实现的特性,但是为每个特定实现都留下了很多选择。(比如都要能执行字节码,但是执行的技术可以自己选择)。

java虚拟机的主要任务就是装载class文件并执行其中的字节码。虚拟机包含一个类装载器,它可以从程序和API中装载class文件。java API中只有程序执行时需要的那些类才会被装载。字节码由执行引擎来执行。

不同java虚拟机中,执行引擎可能实现得非常不同:
- “一次性解释字节码”,是软件实现的虚拟机中,最简单的引擎。
- “即使编译器”,更快、但是消耗内存。这时,在第一次被执行的字节码会被编译成本地机器代码。编译出的本地机器代码会被缓存,当方法以后被调用的时候可以重用。
- “自适应优化器”,这时,虚拟机开始的时候解释字节码,但是会见时运行中的程序活动,并记录下使用最频繁的代码段,程序运行时时,虚拟机会只把活动最频繁的代码编译成本地机器代码,其它的代码由于使用不频繁,继续保留成字节码——由虚拟机继续解释它们。
- 最后一种虚拟机由硬件芯片后成,它用本地方法执行java字节码,这种执行那个引擎实际上是内嵌在芯片里的。

当java虚拟机由主机操作系统的软件实现时,java程序通过调用本地方法和主机交互。
java中有两种方法:java方法和本地方法。
- java方法是由java语言编写,编译成字节码,储存在class文件中。
- 本地方法是由其它语言(比如C、C++,或者汇编语言)编写的,编译成和处理器相关的机器代码。保存在动态链接库中,格式是各个平台专有的。
java方法是平台无关的。
本地方法是平台有关的。
运行中的java程序调用本地方法时,虚拟机装载包含这个本地方法的动态库,并调用这个方法。本地方法是联系java程序和底层主机操作系统的连接方法。

----------------类装载器体系结构:
一个java程序可以使用两种类装载器:启动类装载器和用户定义类装载器。
启动类装载器(系统唯一)是java虚拟机实现的一部分。
java程序能够在运行时安装用户定义的类装载器。这种类装载器能够使用自定义的方式来装载类。

启动类装载器是虚拟机实现的本质部分,但是用户定义类装载器不是。但用户类装载器能够用java编写,能够被编译成class文件,能够被虚拟机装载,能够像其他类一样实例化,他们实际上只是运行中的java应用程序可执行代码的一部分。

由于有用户定义类装载器,所以不必在编译的时候就知道运行中的java程序中最终会加入的所有类。使得在运行时扩展java程序称为可能。但它运行时程序能够决定它需要哪些额外的类,能够决定是使用一个或是更多的用户定义类装载器来装载。

每一个类被装载的时候,java虚拟机都监视这个类,看他到底是被哪个类装载器装载。当被装载的类引用了另一个类时,虚拟机会使用装载第一个类的类装载器来装载被引用的类。

java程序能够从一个或多个类中实例化多个用户定义类装载器。所以需要多少个用户定义类装载器就能创建多少个。被不同的类装载器装载的类存放在不同的命名空间中,它们不能互相访问,除非应用程序显示地允许这样做。
当编写应用程序的时候,从不同源文件装载的类可以分隔在不同的命名空间中。这样就能够使用java类装载器的体系结构来控制任何从不同源文件中装载的代码之间的互相应用,特别是能够阻止恶意代码获取访问和破坏善意代码的权限。

网络移动性的支持:允许实例化用户定义类装载器来知道如何从网络下载class文件。
安全性的支持:允许使用不同的用户定义类装载器装载不同来源的class文件,把不同来源的class文件放置在不同的命名空间中,这就能够限制或阻止不同来源的代码之间的互相访问。

----------------java class文件:
平台无关性:
- 为java程序提供独立于底层主机平台的二进制形式的服务。
- java class文件是可以运行在任何支持java虚拟机的硬件平台和操作系统的二进制文件。
- java编译器把java源文件的指令翻译成字节码,这种字节码就是java虚拟机的“机器语言”。
- java class文件中字节顺序是高位在前,这与使用何种平台产生这个文件和何种平台上使用这个文件都没关系。

网络移动性:
- class文件设计得紧凑,因此可快速在网络上传送。
- 由于java程序是动态链接和动态扩展的,class可以在需要的时候下载。

----------------java API:
java API是运行库的集合,它提供一套访问主机系统资源的标准方法。
所有被装载的class文件和所有已经装载的动态库共同组成了java虚拟机上运行的整个程序。

平台无关性:在每个特定的主机平台上都明确地实现了java虚拟机和java API。

----------------java程序设计语言:
java能够提高开发者的效率,这种效率主要来自java对直接内存操作的约束。
(在C++中:不再使用的对象没有被释放会导致内存泄漏;多次释放一个对象会导致内存冲突。这两种情况都会导致C++程序崩溃。)

提高开发者的效率+为终端用户增强健壮性。

----------------java体系结构的代价:
- 和其它技术(如C++)相比,java程序的执行速度可能较低,这是java在面向网络特性上的主要代价之一(虚拟机性能问题[执行引擎的效率])。
- 因为跨平台,所以要保证在多种虚拟机上都有令人满意的性能。随着代码和对象通过网络在虚拟机之间移动,开发者也无从知晓他们的程序究竟会运行在哪些虚拟机上
- java在内存管理和线程调度上的缺陷,垃圾收集器可以使得许多程序更加健壮,但是在程序运行时的性能加入了一些不确定性(无法确定gc什么时候开始收集垃圾,无法确认是否开始收集垃圾,无法确认垃圾收集要持续多长时间);java虚拟机规范讨论线程调度的地方非常笼统,这种对线程行为的松散规范有利于将java虚拟机移植到许多不同类型的硬件上去,但是这种线程管理使得程序员无法了解应该如何调度线程,无法控制线程调度。
- 为了实现平台无关性,引发的最小公分母问题。各个操作系统之间虽然有许多共性,但是每个操作系统通常都有一些自己的特性。在大多数os上由的特性,可能会被添加到java的os系统服务API中,但是这时还要在不具备这个特性的的os上由API模拟实现它。
- 容易被逆向编译。因为java class文件与java程序语言之间是紧密联系的,和java天生的动态链接特性,所以从一个类到另一个类的引用时符号化的。在java class中,指向另一个类的引用通过字符串清楚地标明了所指向的这个类的名字。如果引用指向一个字段,则这个字段的名称和描述符(字段类别)都会被详细说明;如果这个引用指向的是一个成员方法,则这个成员方法的名称和描述符(返回类型,方法参数数量和类型)也会被详细说明。还包含了自己字段和成员方法的符号引用和可选的调试信息(包含局部变量名称和类型)。
一个class文件的符号信息,以及字节码指令集和java语言之间的密切关系,这些方法使得把java class文件逆向编译为java源码文件相当容易。
(可以用混淆器来混淆你的class文件,通过改变类、字段、方法和、局部变量的名字,但它不改变工作流程)。

----------------总结:
java程序设计语言是一种十分通过的语言,它和其他技术相比有着明显的优势,特别是java能在极大程度上提高程序员的效率,增强程序的健壮性,与老的程序设计技术(比如C、C++)相比,具有过得去的性能。

[看书笔记]《深入java虚拟机》——java体系结构(一)