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 俱乐部