深入理解JVM-类加载及类加载器 (10)

可以确保Java核心库的类型安全:(jdk自带的rt.jar等)所有的Java应用都至少会引用Java.lang.Object类,也就是说,在运行期,这个类会被加载器到Java虚拟机中;如果这个加载过程是由Java应用自己提供的类加载器完成的,那么就很可能在jvm中存在多个Java.lang.Object类的版本,而且这些类之间还是不兼容的,相互不可见的(正是命名空间在发挥着作用)。借助于双亲委托机制,Java核心类库中的类的加载工作都是由启动类(根类)加载器来统一完成。从而确保了Java应用使用的都是同一个版本的Java核心类库,他们之间是相互兼容的。

可以确保Java核心类库所提供的类,不会被自定义的类所替代。

不同的类加载器可以被相同名称(binary name)的类创建额外的命名空间;相同名称的类可以并存在Java虚拟机中,只需要用不同的类加载器加载他们即可。不同类加载器所加载的类之间是不兼容的,这就相当于在Java虚拟机中创建了一个又一个相互隔离的Java类空间,这类技术在多框架中都得到了实际应用。

扩展类加载器类特性介绍 public class MyTest22{ static{ sout("MyTest22 initializer"); } psvm{ sout(MyTest22.class.getClassLoader()); sout(MyTest1.class.getClassLoader()); } } > 1.此时的输出结果是什么? AppClassLoader AppClassLoader > 2.修改本地的扩展类加载器的加载路径。 1. 进入到当前编译的 out路径 2. java -Djava.ext.dirs=./ com.erwa.jvm.MyTest22 > 3.此时的输出结果是什么? AppClassLoader AppClassLoader 4.还是一样的,为什么不是扩赞类加载器加载的呢?因为扩展类加载的类还不能是Class文件的形式,要以jar包的形式加载。 > 5.将当前的com打成jar包 jar cvf com.erwa.jvm > 6.此时的输出结果是什么? AppClassLoader ExtClassLoader > 7. java -Djava.ext.dirs=http://www.likecs.com/ com.erwa.jvm.MyTest22 > 8.此时的输出结果是什么? AppClassLoader AppClassLoader

关于命名空间的补充:

在运行期,一个Java类是由该类的完全限定名(binary name,二进制名)和用于加载该类的定义类加载器共同确定的。

如果同样的名字(即相同的完全限定名)的类是由两个不同的加载器所加载,那么这些类就是不同的。即便.class文件的字节码完全一样,并且从相同的位置加载亦如此。

在Oracle的Hotspot实现中,系统属性sun.boot.class.path如果修改错了,则运行时会出错,信息下图:

image-20200211055535115

类加载器的特例,数组。数组不是由类加载器的加载的,是由JVM加载的。

先有鸡还是先有蛋?

类加载器本身也是一个Java类,他们是怎么加载到JVM当中的呢?

他们是由启动类加载器加载的。BootStrapClassLoader加载的。他不是由Java代码写的,由C++代码编写的。启动的时候回自动加载出启动类加载器的实例。

内建与JVM中的启动类加载器会加载java.lang.ClassLoader以及其他的Java类加载器。

当JVM启动时,一块特殊的机器码会执行,它会加载类加载器与系统类加载器,这块特殊的机器码叫做启动类加载器(BootStarp)

启动类加载器并不是Java类,而其他的加载器则都是Java类

启动类加载器是特定于平台的机器指令,它负责开启整个加载过程

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszsp.html