合肥网站建设-中国互联,做联轴器的网站,漳州正规网站建设价格,软件开发合同模板范本1.jvm组成 JVM组成#xff1a; 1.类加载器 2.运行时数据区 3.执行引擎 4.本地库接口 各组件的作用#xff1a; 首先通过类加载器#xff08;ClassLoader#xff09;会把 Java 代码转换成字节码#xff0c;运行时数据区#xff08;Runtime Data Area#xff09;再把字节码…1.jvm组成 JVM组成 1.类加载器 2.运行时数据区 3.执行引擎 4.本地库接口 各组件的作用 首先通过类加载器ClassLoader会把 Java 代码转换成字节码运行时数据区Runtime Data Area再把字节码加载到内存中而字节码文件只是 JVM 的一套指令集规范并不能直接交个底层操作系统去执行因此需要特定的命令解析器执行引擎Execution Engine将字节码翻译成底层系统指令再交由 CPU 去执行而这个过程中需要调用其他语言的本地库接口Native Interface来实现整个程序的功能。
2.类加载器
下图借用图灵 诸葛老师的流程图respect 2.1 java里的几种类加载器
BootstrapClassLoad 系统级类加载器负责加载支撑JVM运行的位于JRE的lib目录下的核心类库。是C或者C 生成的对象。创建了Launcher类 extClassloader 扩展类加载器负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的Jar类包。属于Launcher类构造方法生成 AppClassload应用程序类加载器负责加载ClassPath路径下的类包主要就是加载开发自己写的那些类。属于Launcher类构造方法生成 也可以自定义加载器负责加载开发者自定义路径下的类包。
Launcher 类部分源码
package sun.misc;public class Launcher {private static Launcher launcher new Launcher();private static String bootClassPath System.getProperty(sun.boot.class.path);private ClassLoader loader;public static Launcher getLauncher() {return launcher;}public Launcher() {ExtClassLoader var1;try {//extClassloader 扩展类加载器 获取在getExtClassLoader()里没有ExtClassLoader 的话会new ExtClassLoader()var1 Launcher.ExtClassLoader.getExtClassLoader();} catch (IOException var10) {throw new InternalError(Could not create extension class loader, var10);}try {//AppClassload应用程序类加载器获取在getAppClassLoader()里没有AppClassLoader的话会new AppClassLoader()。AppClassLoader是应用级默认的类加载器this.loader Launcher.AppClassLoader.getAppClassLoader(var1);} catch (IOException var9) {throw new InternalError(Could not create application class loader, var9);}}
}2.2类加载过程 注主类在运行过程中如果使用到其它类会逐步加载这些类。jar包或war包里的类不是一次性全部加载的是使用到时才加载。懒加载模式。 主要流程 加载 验证 准备 解析 初始化 使用 卸载
加载根据类文件路径找到相应的class文件导入 检测校验字节码class文件的正确性。都是cafe babe 开头的字节码文件。 准备: 给类中的静态变量分配内存空间并赋予默认值 eg:boolean false int 0 解析jvm将常量池中的符号引用替换成直接引用的过程 初始化对静态变量和静态代码块执行初始化工作。
2.3ClassLoader 类加载过程源码 类加载过程都在根加载器抽象类ClassLoader 里有定义或者实现 该ClassLoader 类有两个核心方法 loadClass(String, boolean)实现了双亲委派机制 还有一个方法是findClass()默认实现是空方法。根据要加载的class类路径去实际加载类
package java.lang;
public abstract class ClassLoader {private final ClassLoader parent;/*** 双亲委派加载方式的保证*/protected Class? loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded//校验当前类对象是否已经被加载Class? c findLoadedClass(name);if (c null) {long t0 System.nanoTime();try {//当前加载器有父加载器交给父加载器加载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 statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}//由子类实现的实际加载类的操作 实际实现是URLClassLoader类protected Class? findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);}
}URLClassLoader类 是AppClassLoader 和 ExtClassLoader 的父类。 Launcher类中的静态内部类AppClassLoader部分核心源码 static class AppClassLoader extends URLClassLoader {final URLClassPath ucp SharedSecrets.getJavaNetAccess().getURLClassPath(this);public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {//AppClassLoader 加载的是应用ClassPath路径下的类包final String var1 System.getProperty(java.class.path);final File[] var2 var1 null ? new File[0] : Launcher.getClassPath(var1);return (ClassLoader)AccessController.doPrivileged(new PrivilegedActionAppClassLoader() {public AppClassLoader run() {URL[] var1x var1 null ? new URL[0] : Launcher.pathToURLs(var2);return new AppClassLoader(var1x, var0);}});}//实际加载类调用的是父类URLClassLoader类中的loadClasspublic Class? loadClass(String var1, boolean var2) throws ClassNotFoundException {int var3 var1.lastIndexOf(46);if (var3 ! -1) {SecurityManager var4 System.getSecurityManager();if (var4 ! null) {var4.checkPackageAccess(var1.substring(0, var3));}}if (this.ucp.knownToNotExist(var1)) {Class var5 this.findLoadedClass(var1);if (var5 ! null) {if (var2) {this.resolveClass(var5);}return var5;} else {throw new ClassNotFoundException(var1);}} else {//调用的是父类URLClassLoader类中的loadClassreturn super.loadClass(var1, var2);}}}
Launcher类中的静态内部类ExtClassLoader部分核心源码
static class ExtClassLoader extends URLClassLoader {private static volatile ExtClassLoader instance;public static ExtClassLoader getExtClassLoader() throws IOException {if (instance null) {Class var0 ExtClassLoader.class;synchronized(ExtClassLoader.class) {if (instance null) {instance createExtClassLoader();}}}return instance;}private static ExtClassLoader createExtClassLoader() throws IOException {try {return (ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionActionExtClassLoader() {public ExtClassLoader run() throws IOException {File[] var1 Launcher.ExtClassLoader.getExtDirs();int var2 var1.length;for(int var3 0; var3 var2; var3) {MetaIndex.registerDirectory(var1[var3]);}return new ExtClassLoader(var1);}});} catch (PrivilegedActionException var1) {throw (IOException)var1.getException();}}void addExtURL(URL var1) {super.addURL(var1);}public ExtClassLoader(File[] var1) throws IOException {super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);}private static File[] getExtDirs() {//这里可以看出拓展类加载器 加载的是jre中ext内的相关类String var0 System.getProperty(java.ext.dirs);File[] var1;if (var0 ! null) {StringTokenizer var2 new StringTokenizer(var0, File.pathSeparator);int var3 var2.countTokens();var1 new File[var3];for(int var4 0; var4 var3; var4) {var1[var4] new File(var2.nextToken());}} else {var1 new File[0];}return var1;}}总结 ClassLoad 抽象类里面2个核心方法 loadClass()实现了双亲委派机制 findClass() 根据对应的类路径加载类
3.类加载器中的双亲委派机制 双亲委派加载某个类时会先委托父加载器寻找目标类找不到再委托上层父加载器加载如果所有父加载器在自己的加载类路径下都找不到目标类则在自己的类加载路径中查找并载入目标类。
3.1为什么要设计双亲委派机制 沙箱安全机制自己写的java.lang.String.class类不会被加载这样便可以防止核心API库被随意篡改安全性保证。 避免类的重复加载当父亲已经加载了该类时就没有必要子ClassLoader再加载一次保证被加载类的唯一性。
3.2自定义类加载器父加载器是appClassLoad 自定义类加载器只需要继承 java.lang.ClassLoader 抽象类重写该类有两个核心方法 loadClass()实现了双亲委派机制findClass()默认实现是空方法所以我们自定义类加载器主要是重写findClass方法。
3.3 自定义类加载器打破双亲委派机制 重写继承 java.lang.ClassLoader 抽象类中的loadClass()即可