前提:
java虚拟机(即JVM)能够识别的不是java文件(字节码文件),而是二进制的class文件。
当执行
java HelloWorld
或者
java -jar Xxx.jar
这些命令的时候,会启动java虚拟机,并加载程序运行所需的class文件。
现象:
java程序得以运行。
过程:
那么这个过程中发生的是什么呢?
就是类加载器ClassLoader加载了class文件,然后jvm分配内存,然后表现出行为。
原理:
1,ClassLoader,是一个抽象类,它的子类中出名的有,BootstrapClassLoader,ExtClassLoader,AppClassLoader。
2,BootstrapClassLoader是由C++编写的,无法找到。如下是ClassLoader的java doc中的信息。
The ClassLoader class uses a delegation model to search for classes and resources.
Each instance of ClassLoader has an associated parent class loader.
When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself.
The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
简单解释一句:如果请求加载一个class的话,一个classloader的实例不会立即自己去加载,而是先让父类去加载,不行的话再自己加载。BootstrapClassLoader早于ExtClassLoader早于AppClassLoader。可以保证jvm中只存在一个指定的class对象。
3,ExtClassLoader是java类,是一个内部类,存在于sun.misc.Launcher类中。它用来加载额外的class文件。并且是BootstrapClassLoader授意它去加载。ExtClassLoader主要加载%JAVA_HOME%/jre/lib/ext
,此路径下的所有classes目录以及java.ext.dirs
系统变量指定的路径中类库。
就这个东西简单说明一下。
java1.6引入了外来脚本,可以在jvm中执行script,包括但不限于JavaScript以及groovy等。java内置了JavaScript引擎模块nashorn.jar,而这个模块就在ext目录下。当决定加载JavaScript引擎的时候,就会去ext目录下加载这个jar包。还可以通过设置-D java.ext.dirs参数,设置额外的
录。
NashornScriptEngine(jdk.nashorn.api.scripting.NashornScriptEngineFactory factory, java.lang.String[] args, java.lang.ClassLoader appLoader, jdk.nashorn.api.scripting.ClassFilter classFilter) { /* compiled code */ }
以上仅仅是帮助理解,不一定正确。
另外还有一种场景需要用到这个东西。在RSA加密解密的时候,不想用java提供的方式,而是用第三方的某种方式的话,
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
这个时候,BouncyCastleProvider.class所在的jar包需要放到ext目录下,并且需要修改securityjava.security文件的内容。
参照:https://blog.csdn.net/hechonghui/article/details/52593819
4,APPClassLoader,这个也是java类,存在于sun.misc.Launcher类中。它主要负责加载CLASSPATH目录下的所有class文件。
。。。
写着写着,发现了这篇文章,我还写个毛啊。。。