-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
1,337 additions
and
647 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
|
||
|
||
## ClassLoader | ||
|
||
+ Bootstrap Loader - 负责加载系统类 | ||
+ ExtClassLoader - 负责加载扩展类 | ||
+ AppClassLoader - 负责加载应用类 | ||
|
||
|
||
当执行 java ***.class 的时: | ||
|
||
  java.exe 会帮助我们找到 JRE ,接着找到位于 JRE 内部的 jvm.dll ,这才是真正的 Java 虚拟机器 , 最后加载动态库,激活 Java 虚拟机器。虚拟机器激活以后,会先做一些初始化的动作,比如说读取系统参数等。一旦初始化动作完成之后,就会产生第一个类加载器―― Bootstrap Loader | ||
|
||
  Bootstrap Loader 是由 C++ 所撰写而成,这个 Bootstrap Loader 所做的初始工作中,除了一些基本的初始化动作之外,最重要的就是加载 Launcher.java 之中的 ExtClassLoader ,并设定其 Parent 为 null ,代表其父加载器为 BootstrapLoader 。(Launcher.java在rt.jar)然后 Bootstrap Loader 再要求加载 Launcher.java 之中的 AppClassLoader ,并设定其 Parent 为之前产生的 ExtClassLoader 实体。这两个加载器都是以静态类的形式存在的。 | ||
|
||
  这里要注意的是: Launcher$ExtClassLoader.class 与 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加载,所以 Parent 和由哪个类加载器加载没有关系。 | ||
|
||
|
||
根据指定的name名称装载class。默认的实现中,搜索顺序如下: | ||
|
||
1. 调用 `findLoadedClass(String)`检查是否已加载 | ||
2. 调用 父类的`loadClass(String)` 方法,如果parent==null,则使用内置装载器Bootstrap classloader | ||
3. 调用 findClass(Stirng)查找类 | ||
|
||
如果在上述步骤中,已经发现class,并且resolve标记为true,本方法将调用resolveClass(Class),Class是传入的Class文件 | ||
|
||
ClassLoader 的子类,鼓励覆盖@Override $findClass(String)$,而不是@Override loadClass(String) | ||
|
||
|
||
在没有被重写的情况下,此方法 使用$getClassLoadingLock$ 保证整个类装载过程的同步 | ||
|
||
|
||
```java {.line-numbers} | ||
|
||
/** | ||
* @param name | ||
* 类名 | ||
* @param resolve | ||
* true: resolve the class | ||
* @return Class | ||
* @throws ClassNotFoundException | ||
* If the class could not be found | ||
*/ | ||
protected Class<?> loadClass(String name, boolean resolve) | ||
throws ClassNotFoundException | ||
{ | ||
//同步锁,保证整个类装载过程的同步 | ||
synchronized (getClassLoadingLock(name)) { | ||
// 1. 检查类是否被装载 | ||
Class<?> c = findLoadedClass(name); | ||
if (c == null) { | ||
long t0 = System.nanoTime(); | ||
try { | ||
//向父 loader委派 | ||
if (parent != null) { | ||
c = parent.loadClass(name, false); | ||
} else { | ||
c = findBootstrapClassOrNull(name); | ||
} | ||
} catch (ClassNotFoundException e) { | ||
// ClassNotFoundException thrown if class not found | ||
// from the non-null parent class loader | ||
} | ||
if (c == null) { | ||
// If still not found, then invoke findClass in order | ||
// to find the class. | ||
long t1 = System.nanoTime(); | ||
c = findClass(name); | ||
|
||
// this is the defining class loader; record the stats | ||
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); | ||
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); | ||
sun.misc.PerfCounter.getFindClasses().increment(); | ||
} | ||
} | ||
if (resolve) { | ||
resolveClass(c); | ||
} | ||
return c; | ||
} | ||
} | ||
|
||
``` | ||
|
||
|
||
使用给定的类加载器, 返回与 name 关联的class或interface 的Class 对象. | ||
给定类的完全限定名(getName 返回的格式),此方法尝试查找、加载和链接类或接口。指定的类。使用指定的加载器加载类或接口。如果参数为 null, 通过 bootstrap 加载,只有当initialize==true&&类没有被初始化过,才会初始化类。 | ||
|
||
|
||
+ 如果name 传入一个基本类型或者void, 将尝试在 未命名的package的包里定位一个自定义类,因此这个方法不能用户获取任何基础类型和void的Class | ||
+ 如果是一个数组 | ||
|
||
|
||
|
||
|
||
```java {.line-numbers} | ||
/** | ||
* Returns the {@code Class} object associated with the class or | ||
* interface with the given string name, using the given class loader. | ||
* Given the fully qualified name for a class or interface (in the same | ||
* format returned by {@code getName}) this method attempts to | ||
* locate, load, and link the class or interface. The specified class | ||
* loader is used to load the class or interface. If the parameter | ||
* {@code loader} is null, the class is loaded through the bootstrap | ||
* class loader. The class is initialized only if the | ||
* {@code initialize} parameter is {@code true} and if it has | ||
* not been initialized earlier. | ||
* | ||
* <p> If {@code name} denotes a primitive type or void, an attempt | ||
* will be made to locate a user-defined class in the unnamed package whose | ||
* name is {@code name}. Therefore, this method cannot be used to | ||
* obtain any of the {@code Class} objects representing primitive | ||
* types or void. | ||
* | ||
* <p> If {@code name} denotes an array class, the component type of | ||
* the array class is loaded but not initialized. | ||
* | ||
* <p> For example, in an instance method the expression: | ||
* | ||
* <blockquote> | ||
* {@code Class.forName("Foo")} | ||
* </blockquote> | ||
* | ||
* is equivalent to: | ||
* | ||
* <blockquote> | ||
* {@code Class.forName("Foo", true, this.getClass().getClassLoader())} | ||
* </blockquote> | ||
* | ||
* Note that this method throws errors related to loading, linking or | ||
* initializing as specified in Sections 12.2, 12.3 and 12.4 of <em>The | ||
* Java Language Specification</em>. | ||
* Note that this method does not check whether the requested class | ||
* is accessible to its caller. | ||
* | ||
* <p> If the {@code loader} is {@code null}, and a security | ||
* manager is present, and the caller's class loader is not null, then this | ||
* method calls the security manager's {@code checkPermission} method | ||
* with a {@code RuntimePermission("getClassLoader")} permission to | ||
* ensure it's ok to access the bootstrap class loader. | ||
* | ||
* @param name fully qualified name of the desired class | ||
* @param initialize if {@code true} the class will be initialized. | ||
* See Section 12.4 of <em>The Java Language Specification</em>. | ||
* @param loader class loader from which the class must be loaded | ||
* @return class object representing the desired class | ||
* | ||
* @exception LinkageError if the linkage fails | ||
* @exception ExceptionInInitializerError if the initialization provoked | ||
* by this method fails | ||
* @exception ClassNotFoundException if the class cannot be located by | ||
* the specified class loader | ||
* | ||
* @see java.lang.Class#forName(String) | ||
* @see java.lang.ClassLoader | ||
* @since 1.2 | ||
*/ | ||
@CallerSensitive | ||
public static Class<?> forName(String name, boolean initialize, | ||
ClassLoader loader) | ||
throws ClassNotFoundException | ||
{ | ||
Class<?> caller = null; | ||
SecurityManager sm = System.getSecurityManager(); | ||
if (sm != null) { | ||
// Reflective call to get caller class is only needed if a security manager | ||
// is present. Avoid the overhead of making this call otherwise. | ||
|
||
// | ||
caller = Reflection.getCallerClass(); | ||
if (sun.misc.VM.isSystemDomainLoader(loader)) { | ||
ClassLoader ccl = ClassLoader.getClassLoader(caller); | ||
if (!sun.misc.VM.isSystemDomainLoader(ccl)) { | ||
sm.checkPermission( | ||
SecurityConstants.GET_CLASSLOADER_PERMISSION); | ||
} | ||
} | ||
} | ||
return forName0(name, initialize, loader, caller); | ||
} | ||
|
||
``` | ||
|
||
### Tomcat中的类加载器 | ||
|
||
在Tomcat目录结构中,有三组目录(“/common/*”,“/server/*”和“shared/*”)可以存放公用Java类库, | ||
|
||
此外还有第四组Web应用程序自身的目录“/WEB-INF/*”,把java类库放置在这些目录中的含义分别是: | ||
+ common:类库可被Tomcat和所有的Web应用程序共同使用。 | ||
+ server:类库可被Tomcat使用,但对所有的Web应用程序都不可见。 | ||
+ shared:类库可被所有的Web应用程序共同使用,但对Tomcat自己不可见。 | ||
+ /WebApp/WEB-INF:类库仅仅可以被此Web应用程序使用,对Tomcat和其他Web应用程序都不可见。 | ||
|
||
![tomcat类加载器机制](.images/ClassLoader详解/2018-11-07-14-27-09.png) | ||
|
||
|
||
|
||
JVM区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。 | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.