Java是跨平台的, 指得是Java编译成的class文件,可以在(32/64) .* (Oracle/IBM/…) .* (Linux/Win)等不同的JVM实现下面运行,Java源文件在不同的JVM下面不需要重新编译。但在不同的OS下面可能需要安装不同的JVM(这个程度上说,某个JVM实现不是跨平台的)。
类加载过程
首先要理解什么是jvm,jre,jdk,这里就不再详细叙述,简单的说jdk包含jre,jre包含jvm。jvm只是执行编译后的class文件的,class文件中存储的是操作指令,而jvm则是一个指令执行引擎。
java类加载过程是有jvm控制的,用户代码不可以控制。具体过程分为 1加载 2验证 3 准备 4 连接 5 初始化 6 使用 7 卸载。
在加载过程中主要是根据一个类的全限定名来加载该类的二进制流到内存中,并形成该类的内存结构(方法区中),最后并形成代表该类的class文件(方法区中)。
验证过程相对简单,主要是由jvm根据指定的规则来验证该class文件是否合法,是否有错误,比如在网络传输的过程中不完整等等。
准备阶段则是正式为该类的静态字段分配内存并赋初值,通常是0值和false。
连接则是把class文件中的符合引用转换为直接引用的过程,在class文件中存储的是符号引用。
初始化则是根据用户的设定正式为静态字段赋值,按照类中的顺序,包括static代码块。不同的顺序,结果可能不同。
卸载则是把该类从内存中卸载掉。
类加载器
在整个类加载过程中,只用类的加载可以有用户控制,而在类加载阶段则又出现了一些很实用的技术,类加载器。
在java中类加载器使用双亲委派模型来加载类,bootstrap classloader 是有c++写的,是根加载器。然后下面是ext classloader 和AppClassLoader,所谓双亲委派加载是指当一个类加载器在加载一个类时,首先由该类加载器的父加载器加载,如果父加载器不能加载的话,才有该类加载器加载类。这里的父并不是extend而是composite。看java ClassLoader 的源码 ClassLoader 是抽象类,是所有类加载器的父类。classload类 源码http://blog.csdn.net/chaofanwei/article/details/12858833
URLClassLoader类源码 http://blog.csdn.net/chaofanwei/article/details/12858971
类结构图:
类加载路径:
BootstrapLoader : sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
这三个系统参量可以通过 System.getProperty() 函数得到具体对应的路径。
sun.boot.class.path 一般是java_home/lib
java.ext.dirs 一般是java_home/lib/ext
每个类加载器都有一个名称空间,子类加载器可以看到父类加载器空间内的类,而反过来不可以。
每个类的唯一性是有该类的类加载器和类共同决定的。
线程上下文类加载器,是一个比较特殊的类加载器,可以被根类加载器调用用来加载位于classpath中的类。