Java程序启动的时候,不会一次性的将程序需要用到的所有类加载到内存中。JVM会先加载基础类,其他类等到需要使用的时候再进行加载。
什么叫做“需要使用的时候”了?通常而言有如下几种情况:
new
关键字第一次使用非基础类
,比如自己定义的PersonService
这类的。Class.forName()
的时候。非基础类
的静态成员
的时候。简单而言:JDK默认提供了3个ClassLoader,Bootstrap、Extension、App 3个,前2者通常用于加载JDK自身的jar或者class,app加载的是我们开发过程中引入的包。
Bootstrap Classloader
时C++
编写的最底层的类加载器,它会加载系统最底层的类,比如rt.jar
和charsets.jar
这些类。
可以通过如下代码获取加载了哪些
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toExternalForm());
}
Extension Classloader
被称为扩展类加载器,默认加载C:\Program Files\Java\jre1.8.0_162\lib\ext
下的相关类。
App Classloader
称为应用类加载器
,加载我们应用程序下的 jar包或者 class 文件。该加载器默认情况下,是我们应用程序中引入的包的加载器。
简单而言:当需要加载一个class 的时候,默认情况下会通过如下顺序进行查找:自定义的ClassLoader ➡ AppClassloader ➡ ExtensionClassLoader ➡ BootstrapClassloader。
JVM为何要如此设计?从安全来说,保证了核心的class 只会被加载一次,不会被自定义的Classloader篡改。
从如下图可以看出:
结合JVM的结构进行理解,Classloader 存储在哪个位置,该图是JDK7
下的JVM内存结构。
请注意在线程共享
中的方法区
.
JDK7是存储在 方法区中的 PermGen
JDK8是存储在 堆中的 MetaSpace
中。
可以参考:
本章只是ClassLoader
的入门,其中最关键的是自定义ClassLoader
后续专门通过一个章节讲解。
您有任何建议和意见,请Email联系: hicode_club@163.com
转载请保留出处 HiCode 俱乐部