您的位置:首页 > 编程语言 > Java开发

深入学习JAVA虚拟机笔记

2015-07-16 19:30 501 查看

深入学习JAVA虚拟机第二版

第一章    java体系结构介绍

Java的核心优势是跨平台,java的核心技术就是java虚拟机。Java设计之初的目的是嵌入式设备。

 

1.1    为什么使用java?
因为由java的体系结构决定java具有适合用于网络环境的能力,它可以保证安全的、健壮的、平台无关的程序通过网络传播,在很多不同的计算机和设备上运行。(具有平台无关性、安全性、网络移动性)

1.2    Java体系结构包括:
Java虚拟机、Javaclass文件、Java API、Java语言

其中java API
和java 虚拟机一起组成了java运行时系统(java平台)

Ø  java虚拟机
         Java虚拟机是一台抽象的计算机,规范定义了每个java虚拟机都要实现的特性,但是具体的实现方式很灵活可以由多种选择。

         Java虚拟机的主要任务是装载class文件并执行其中的字节码。由类装载器装载class文件,由执行引擎执行字节码(将字节码编译成本地代码;有多种执行引擎)。

                                                                     

  

    
类装载器分:系统类加载器和用户自定义类加载器。

系统装载器是由java虚拟机实现的本质部分。

用户自定类装载器实际是运行中的java应用程序可执行代码的一部分,可以被编译为class文件,能够被虚拟机装载,还能够像其他对象一样被实例化。用户自定义类装载器是普通的java对象,它的类派生自java.lang.ClassLoader。用户能够以自定义的方式加载类,不必在编译时就知道运行中的程序最终会加载的所有类。使得在运行时扩展java应用程序成为可能。运行时的每一个类装载器都有它自己的命名空间,不同类装载器装载的类不能互相访问,(这是一种安全策略)。

Java中有两种方法:java方法——由java语言编写       平台无关
本地方法——由其他语言编写     平台相关
Ø  Javaclass
文件

对平台无关性的支持:
当编译和连接一个C++程序时,获得的可执行二进制文件包含了目标处理器的机器语言,故只能在指定的硬件平台和操作系统上运行。而且这个二进制文件的字节顺序依赖于具体平台的属性。

而java编译器把java源文件编译成javaclass
文件,java class文件可以运行在任何支持java虚拟机的硬件平台和操作系统。Java class
文件的字节顺序是高位在前,与平台无关。

对网络移动性的支持:
Class 文件设计的紧凑,可以快速的在网络上传送。Java程序时动态链接和扩展的,可以在需要的时候下载class文件,最大限度减少用户的等待时间。

Ø  JavaAPI
Java API通过支持平台无关性和相关性,使得java适应于网络应用。

Java API是运行库的集合,它提供一套访问主机系统资源的标准方法。

    对平台无关性的支持:

在一个平台能够支持java程序以前,必须在这个平台上明确的实现API功能。为访问主机上的资源API
调用本地方法,java 程序就不再需要调用本地方法了。通过这种方法,java API
为java程序提供了平台无关性支持。

具有伸缩性。Java
提供不同的版本,(JAVAEE,JAVASE,JAVAME)不同版本提供不同的API,面向不同的目标领域。

对网络移动性的支持:
当java API的方法进行任何有潜在威胁的操作前,都会通过查询安全管理器来检验是否得到授权。

Ø  Java语言
优点:提高开发者效率,应用领域广不仅仅是网络领域

缺点:执行速度较慢

Java在运行时执行严格的类型规则,没有指针,垃圾自动收集(c++中new完需要delelte,否则内存泄露或者内存冲突,java中不需要delete),数组边界检查(java中当越界时抛出异常,而c++中越界时不报错)。

对平台无关的支持:
基本数据类型的值域和行为都是由语言自己定义的,与平台无关。

1.3    Java体系结构的代价
执行速度较低(把java程序编译成单独的可执行程序的办法可以提高性能,但是这却牺牲了java的动态扩展特性)。

内存管理和线程调度上有缺陷。垃圾收集器什么时候回收垃圾不确定。

最小公分母选择。每个操作系统会有一些自己的特性,对给程序提供访问操作系统资源的API就不得不决定究竟支持哪一种特性。一般会选择大多数操作系统都具有的特性进行支持。

容易被逆向获取源文件。因为java是动态链接的,从一个类到另一个类的引用时符号化的。在静态链接的可执行过程中类之间的引用只是直接的指针或者偏移量。而java
从一个类引用另一个类是通过字符串明确的表明所指向的类的名字。(可以通过混淆器,混淆class文件,能增加逆向难度)

第二章    平台无关

2.1 为什么要平台无关?

在网络环境下,程序平台无关方便系统管理员的工作。

在嵌入式设备中,平台无关也简化了系统管理员的工作。

平台无关能够减少开发和多个平台上部署应用程序的成本和时间。

2.2 影响平台无关性的因素

Java平台的部署。由于java广泛的需求,大多数设备都已经部署了java平台。

Java平台的版本。针对新java平台编写的程序不一定能再老版本上运行。

本地方法。如果调用了javaAPI以外的本地方法将使程序平台相关。

非标准运行时库。Java平台可以由许多开发商来实现,每个开发商必须提供javaAPI标准运行时库,但是有的开发商还会提供其他库。如果这个非标准运行时库调用了本地方法,那么调用这个库的程序就是平台相关的。

对虚拟机的依赖。因为不同虚拟机的垃圾收集器和线程调度可能会不同,Java程序需遵循原则:不依赖finalization和thread prioritization来达到程序的正确性,来保证平台无关。

对用户界面的依赖。因为不同硬件和操作系统的用户接口不同,在界面设计时必须使不同平台上的用户用起来都感到愉快。

测试。应该尽可能在所有希望运行的平台上对java程序进行测试。

2.3平台无关的步骤

选择程序要运行的平台集合。

在一个平台上的java平台编写运行程序。只调用javaAPI,不依赖垃圾收集器及时终结的正确性,也不依赖线程的优先级。

         在所有平台上测试程序。

2.4 平台无关的策略

         在java平台的实现中既要求必须的java标准组件的存在又允许开发商作出扩展。开发人员可以在平台无关性和其他性能之间进行权衡后作出选择。

         (java平台无关性,消弱了操作系统的垄断地位)

第三章    安全

面向网络的软件技术除了要解决平台独立问题还必须解决的另一个技术难题就是安全。

3.1为什么需要安全性。

因为网络允许多台计算机共享数据和分布式处理,所以它提供了一条入侵计算机系统的潜在途径。

3.2java是怎么保证安全性的?

Java提供了一个扩展的内置安全模型,保护终端用户免受从网络下载的、来自不可靠来源的、恶意程序、善意程序中bug的侵犯。Java提供了一个用户可配置的“沙箱”,在沙箱中用户放置不可靠的java程序,沙箱对不可靠程序的活动进行限制。并且java引入了代码签名和认证的信任模式。

组成沙箱的基本组件:
Java虚拟机的类装载器结构、java虚拟机的class文件检验器、Java虚拟机中的内置的安全特性、安全管理器以及javaAPI

Ø  类装载器体系结构
作用:防止恶意代码区干涉善意的代码(通过由不同的类装载器装入的类提供不同的命名空间实现)。保护被信任类库的边界(通过使用不同的类装载器装载可靠的包和不可靠的包,不同包有不同访问权限来实现)。将代码归入某类,该类确定了代码可以进行哪些操作。

Ø  Class<
c62a
/span>文件检验器

保证装载的class文件内容有正确的内部结构。因为一个class文件实质上是一个字节序列,所以虚拟机无法区分class文件时由java编译产生的还是由黑客特制的。Class文件检验器要进行四趟扫描来完成它的操作。第一趟在类被装载时进行,确认所有跳转指令将会达到另一条合法的指令。第二趟扫描在连接时进行,确认数据类型遵从java语义。第三趟扫描在连接时进行,对字节流进行数据分析,确认这些字节流代表的是类的方法。第四趟扫描在动态连接时进行,确认被引用的类字段和方法确实存在。

Ø  Java虚拟机中的内置的安全特性
类型安全的引用转换、结构化的内存访问(无指针操作)、自动垃圾收集、数组边界检查、空引用检查、并未指明运行时的数据空间在java虚拟机内部是怎样分布的、异常的结构化错误处理

Ø 安全管理器和java API
保护虚拟机外部资源不被虚拟机内运行的恶意或有漏洞代码侵犯。定义了沙箱的外部边界。安全管理器主要负责两个方面的工作:说明一个安全策略以及执行这个安全策略。

Ø  代码签名和认证
支持认证代码是值得信任的。对程序代码区分不同的信任度。

第四章    网络移动性

4.1 为什么需要网络移动性?

         网络发展——>客户机服务器模式——>三层模型——>四层模型……——>分布式处理

分布式处理模式综合了网络和处理器发展的优点,将进程分布在多个处理器上运行,并允许这些进程共享数据。分布式系统的缺点:更难管理。比如要升级一个软件时,管理员不得不分别升级每台计算机上的软件。

解决上述管理难的办法:将软件存储在网络中的一台中央计算机上,当终端用户需要用该软件的时候,这个中央计算机将该软件的可执行程序通过网络传送到终端用户的计算机上运行。(这个就是网络移动性,即通过网络将代码传送到另一个处理器上执行)

在有网络移动性之前,软件时通过光盘等介质来发布的。网络移动性使得软件的安装和升级更加方便。安装和升级可以自动进行。

4.2 java体系结构对网络移动性的支持

Java体系结构对网络移动性的支持和它对平台无关性和安全性的支持密不可分。平台无关性,一个版本就可以对付所以的计算机;安全性,用户就算从不信任的来源下载class文件,也充满自信。

此外,java体系结构对在网络上传送程序的时间进行了管理,class文件可以单独的在网络上传送,而且其本身也设计紧凑,同时由于java程序时动态链接的,用户不需要下载全部class文件就可以先运行程序了;java程序还是动态扩展的,可以延迟到程序运行时才装载所需class文件。Class文件也可以打包成jar包在网络上一次性传送,减少http握手次数,节约时间。

第五章    Java虚拟机

5.1Java虚拟机的生命周期

一个运行时的java虚拟机实例的天职就是负责运行一个java程序。当启动一个java程序时,一个虚拟机实例也就诞生了,当程序关闭退出时,虚拟机实例也就随之消亡。运行了几个java程序就要有几个java虚拟机。

Public staticvoid main(String[] args)方法是java虚拟机入口,作为初始线程的起点。其他线程都是由这个线程启动的。Java虚拟机里有两种线程:守护线程(由虚拟机自己使用的)和非守护线程

5.2 java虚拟机的体系结构

Java虚拟机规范对运行时数据区只有抽象描述,不同虚拟机可以根据不同平台有不同实现。

运行时数据区中的方法区和堆是由所有线程共享的。

方法区中的数据的访问必须设计成线程安全的。方法区的大小不必是固定的,也不必是连续的,方法区可以在一个堆中自由分配。虚拟机会在方法区中存储所装载的类的类型信息(类权限定名(类所在包.类名)、类的父类全限定名、类的类型是接口还是类类型、类的访问修饰符、类的有效列表、常量池、静态变量……)。当类不再使用时,java虚拟机的垃圾收集器卸载这个类。常量池中的数据就像数组一样通过索引访问。

Java程序在运行时创建的所有类实例和数组都放在堆中。堆中的数据的访问也必须设计成线程安全的。(使用数据锁)堆中的内存回收问题通常由垃圾回收器解决(但并不是java虚拟机规范的强制要求)。堆空间也不必是连续的内存区,可以动态扩展或收缩。

每一个新线程被创建时,它都将得到自己的PC寄存器(程序计数器)(当线程在执行的是一个方法时,PC寄存器的值将总是指示下一条将被执行的指令)以及一个java栈(保存局部变量,被调用时的传入参数,返回值,运算中间结果)java栈由栈帧组成,是向下生长的。

每当调用了一个java方法时,虚拟机都会在该线程的java栈中压入一个新帧,这个帧就是当前帧。当方法返回时(return返回或抛出异常返回),虚拟机会将当前栈帧弹出释放。Java栈上的数据是各个线程私有的,不需要考虑数据同步问题。栈可以是连续内存也可以是不连续内存。

本地方法栈是与本地方法相关的数据区。当需要用到本地方法时,保存java栈不动,虚拟机运行到本地方法栈中。

5.3数据类型

Java语言中的所有基本数据类型也都是java虚拟机中的基本类型。boolean类型比较特殊,当源码编译为字节码时,会用int或者byte表示boolean。ReturnAdress类型是用来实现finally字句的,程序员不能使用。Java虚拟机规范没有定义数据类型的位宽,位宽是由具体的虚拟机实现的设计者决定的。

5.4执行引擎

Java虚拟机实现的核心是它的执行引擎。在java虚拟机规范中,执行引擎的行为使用指令集来定义。对于每条指令,规范都详细规定了当实现执行到该指令集时应该处理什么。执行引擎作为运行时的实例就是一个线程。所有属于用户运行程序的线程都是实际工作的执行引擎。每一条指令包含操作码和操作数。方法的字节码流是由指令序列构成的。执行引擎一条一条的执行指令。

5.5java虚拟机的实现

Java虚拟机规范的灵活性给了设计者很大的自由。实现必须能够辨别class文件,必须遵守class文件包含的java代码语义。除此之外的具体实现如数据如何组织、如何发现类等由设计者决定。

第六章    垃圾收集

6.1为什么要使用垃圾收集?

         即内存回收,当一个对象不再被程序引用时,它所使用的堆空间可以被回收。在释放不再被引用的对象的过程中,垃圾收集器运行将要被释放的对象的终结方法(finalizer)

         除了释放不再被引用的对象,垃圾收集器还要处理堆碎块。

         垃圾收集把用户从释放占用内存的重担中解救出来。帮助程序保证完整性,程序员不至于错误释放内存而导致程序奔溃。

         缺点:加大了程序负担,可能影响程序性能。

6.2 垃圾收集算法

         要做两件事:检测出垃圾、回收垃圾

         通常通过建立一个根对象集合并且检测根对象和某个对象之间是否存在引用路径,若是,则认为这个是活动的对象,否则认为是垃圾。

引用计数收集器:

         堆中每个对象都有一个引用计数。对象被引用时计数加1,当对象超过生存期或者被置为新值时计数减1,当计数值为0时,对象被当成垃圾收集。优点:速度快。缺点:无法检测出循环即对象间相互引用。

Ø  跟踪收集器:
         从根节点开始跟踪,遇到对象打上标记。当跟踪结束时,没有打上标记的对象可以被收集。

Ø 压缩收集器:
把活动的对象越过空闲区滑到堆的一端,是解决堆碎块的策略。

Ø  拷贝收集器:
把所有活动对象移动到新区域。

Ø  自适应收集器:
不选择某一种特定的垃圾收集算法,而是使用多种技术,以便在每种技术最擅长的场合使用它们。

Ø 渐进式收集器:(火车算法)
         不是一次发行并回收所有不可触及的对象,而是每次发行并回收一部分。

6.3终结

         垃圾收集器运行对象的终结方法,将对象终结。

         每个对象有三种状态:可触及的、可复活的(从根节点开始的追踪图中不可触及,但是有可能在垃圾收集器执行某些操作(执行终结方法)时可触及)、以及不可触及的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 虚拟机