一、虚拟机体系结构
1、 执行引擎:
(1)由软件实现的执行引擎,每次都一次性解析字节码;
(2)“即时编译器”(just-in-time complier),第一次被执行的字节码会被编译成本地代码,
后续的方法调用都直接执行本地代码,这种方法更快但更耗内存;
(3)自适应优化器。在执行开始的时候会解析字节码,同时会监控程序的活动,记录那些
调用频繁的代码段,将它编译成本地方法缓存起来,一个好的自适应优化器可以使得java
虚拟机80-90%都执行本地代码;
(4)由硬件实现。直接嵌入硬件芯片中,它用本地方法执行字节码。
2、 类装载器
(1) 虚拟机内置一个系统类加载器,他没有父类加载器;
(2) 用户可以使用java代码自定义用户类加载器,以下是一个继承网络类加载器的实例:
import java.net.*; public class ConfigClassLoader extends java.net.URLClassLoader { /** * Creates a new instance of ConfigClassLoader. */ public ConfigClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent); } public String toString() { URL[] urls = getURLs(); StringBuffer sb = new StringBuffer(getClass().getName()); sb.append(" for: "); for (int i=0; ((urls != null) && (i<urls.length)); ++i) { sb.append(urls[i].toString()).append(' '); } return sb.toString(); } }
调用实例:
ConfigClassLoader cl = new ConfigClassLoader(new URL[] {configPath}, Configuration.class.getClassLoader());
(3) 当一个类有用户自定义的类加载器加载,它所引用的其他类都是用该自定义的类加载器加载;
(4) 每一个自定义的类加载器都有自己的命名空间,不同的命名空间不能相互访问,除非在程序里面显示声明(public、protected修饰符);
(5) 类加载器通过双亲委派机制来加载类,就是说每个用户自定义的类加载器必须有一
个父加载器,当使用一个类加载器加载类时,会首先传递给父加载器加载,如果父
加载器还有父加载器,会继续向上传递,直到jvm提供的启动类加载器。
3、 class文件
(1) 由java虚拟机的“机器语言”来替代目标处理器的机器语言,达到平台无关性的目的;
(2) Class文件的设计紧凑加上它可以按需从任意可以访问的位置通过类加载器动态加
载,使得java的网络移动性大大加强。
4、 Java程序设计语言的缺陷
(1) 性能问题。Java虚拟机经过在一个解释器上执行字节码->即时编译器->自适应优化
器性能有了较大改善,但开发者无法确定自己开发的程序在哪一种虚拟机上运行。
当然,Java是一种非常灵活的工具,它提供了很多方法去接解决潜在的性能问题,
如随程序附带虚拟机、把对时间要求很严格的模块用本地方法实现、预编译代码(
但这样就损失了Java的动态扩展能力,通常嵌入式系统中就会将程序预编译好,
直接嵌入到ROM中);
(2) 内存管理。垃圾回收期尽管可以使程序更加健壮,但也给程序运行时的性能带入了
不确定性,你无法确认垃圾回收器什么时候开始收集垃圾,无法确认垃圾回收器是
否开始收集垃圾,因为无法确认它要持续多久。
(3) 线程调度。Java虚拟机规范讨论线程调度的地方非常笼统,这种对线程行为的松散
规范有利于将Java虚拟机移植到许多不同类型的硬件上去,但这样就使得程序员
无法了解应该如果调度线程。
(4) 最小公分母。为了实现平台无关性,Java在任何尝试提供跨平台的API上都会出现
固有的困难。想要给程序提供访问任何操作系统的系统服务功能的api,就不得不决
定究竟支持哪一些特性。如果该特性只有一种操作系统上存在,API的设计者很有
可能会决定不支持改特性,如果某个特性在大部分的操作系统中,但不是所有的,
设计者可能会决定无论如何都要添加对这个特性的支持。这时就需要在不支持这种
特性的系统平台上有API模拟实现它。这些最小公分母的选择都会或多或少得罪
相关操作系统的开发者和终端用户。
(5) 易于反编译。因为java class文件包含了类、方法、字段的详细信息以及字节码指令
集等,很易于反编译,当然可以通过代码混淆器,通过更改类、字段、方法和局部
变量名来修改类,同时不会改变程序的工作流程,增加解读的难度。