➢编译器将Robot.java源文件编译为Robot.class字节码文件 ➢ClassLoader将字节码转换为JVM中的Class <Robot>对象 ➢JVM利用Class <Robot>对象实例化为Robot对象
java的类加载机制分为:Bootstrap class loader、Extensions class loader和System class loader,这些class loader可以加载class文件、jar包、xml配置文件等。前两者和jvm配置有关,而System class loader则可以由程序员自己指定,下面本文将介绍两种System class loader的方式。
php header('Content-Type:text/html;charset=utf-8'); function classLoad1($className){ var_dump($className $className.'.class.php'; if(file_exists($classPath)){ require_once $classPath; } } function classLoad2 '); spl_autoload_register('classLoad2'); new Huskies(); 解析: 首先new Huskies();实例,然后spl_autoload_register ('classLoad1');相当于是spl_autoload_register('classLoad1(new Huskies())');然后找 这个函数没有发现Huskies.class.php 另外如果想把某个放在开头的话,就得spl_autoload_register('classLoad2',true,true);即可 结构:
都是加载到JVM中的),所以使用ResourceUtil.getFile("classpath:xxxx.txt")方法是不可以读取到的,在JVM中是没有绝对路径的,所有的路径都是依托于读取文件的当前类对应的classload 来加载的,所以我们需要先获取到当前类的classload,然后通过classload的路径找文件相对于classload的相对路径,这时候,我们就需要使用上面的方法来读取。
示例 package com.dhb.classload; public class InitDemo { static { System.out.println("InitDemo static (1).使用new关键字实例化对象 package com.dhb.classload; public class NewClass { static { System.out.println package com.dhb.classload; public class ReflectClass { static { System.out.println("ReflectClass package com.dhb.classload; public class SuperClass { static { System.out.println("SuperClass init SubClass init ... 2.1.4.当虚拟机启动时,用户需要指定一个执行的主类,虚拟机会首先初始化这个主类 package com.dhb.classload; public class
java.io.FileWriter;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import classload.MyClassLoad javax.tools.ToolProvider;public class LoadJava { public static final String javaCode = "package classload Exception { // 把 java String 存储到文件 String fileName = "/Users/XXXXXXX/Documents/demo/java/classload ClassLoader pcl = new MyClassLoad("/Users/XXXXXXX/Documents/demo/java/"); Class c = pcl.loadClass("classload.HelloWorld2
Oracle HotSpot JVM的体系结构: JVM主要组件包括,类加载器,运行时内存区,以及执行引擎,程序员主要关注的应该是运行时区域这块了, 回顾下类加载器的顺序: ->Boostrap ClassLoad 引导类,加载java规范定义和接口声明主要是/jre/lib/rt.jar -> Ext ClassLoad 加载扩展类 /jre/lib/ext/*jar -> (System Class Path)App ClassLoad 加载class path环境内的jar -> (User Difine ClassLoad) //用户自定义的加载器 需要继承ClassLoad抽象类,重写其中的一些方法
作用 编译器先把java文件编译成class字节码文件 ClassLoad会把字节码文件转换成jvm中的Class对象 jvm再把class对象转成实例对象 ClassLoad在java 中有着非常重要的作用 它是java的核心组件,所有的class都是通过ClassLoad进行加载的,ClassLoad负责将class文件里的二进制流输入到系统中交给jvm进行连接,初始化操作。
以下是类卸载日志: //虚拟机会卸载掉本类加载的所有对象 //详细日志: //发现[d://dyn1.jar]改变,开始重载【com.linapex.dyn.code4.classload.HotSwapURLClassLoader @b753f8】对象 //当前需要重载的对象【com.linapex.dyn.code4.classload.HotSwapURLClassLoader@b753f8】,与新实例化的对象【com.linapex.dyn.code4 .classload.HotSwapURLClassLoader@1cb25f1】java.io.PrintStream@1ac1fe4 //发现新文件:com.linapex.code.email.UserManagerComponent
System.out.println(Child.v); } } 通过JVM参数-XX:+TraceClassLoading运行得到以下结果 [Loaded com.guanjian.Parent from file:/E:/classload /out/production/classload/] [Loaded com.guanjian.Child from file:/E:/classload/out/production/classload
反射 demo代码: package classload; public class ClassLoadStaticReflect { static { System.out.println { public static void main(String[] args) throws ClassNotFoundException { Class.forName("classload.ClassLoadStaticReflect ,发现父类ClassLoadSuper先被加载,因此当初始化一个类时,发现其父类还未初始化,则先触发父类的初始化 虚拟机启动时,定义了main()方法的那个类先初始化 demo代码: package classload
新建一个java文件,保存在相应的目录 用cmd命令进入到world类的上级目录,运行javac命令,生成.class文件 创建自己定义的classload类 //继承ClassLoader类,重写
创建自己定义的classload类 //继承ClassLoader类,重写findclass方法。
if (k == NULL) { // Use VM class loader PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time ); JavaThread* jt = (JavaThread*) THREAD; PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time (), ClassLoader::perf_app_classload_selftime(), ClassLoader::perf_app_classload_count(), jt->get_thread_stat()->perf_recursion_counts_addr
URLClassLoader:继承自SecureClassLoader,支持从jar文件和文件夹中获取class,继承于classload,加载时首先去classload里判断是否由启动类加载器加载过。
myClassLoader = new MyClassLoader(); Object o = myClassLoader.classLoader.loadClass("com.jvm.classload.Son 父类对象:"+o.getClass().getSuperclass()); Object c = myClassLoader.classLoader.loadClass("com.jvm.classload.MyClassLoader myClassLoader对象的类加载器:"+myClassLoader.getClass().getClassLoader()); } } 控制台输出: Son类对象:class com.jvm.classload.Son Son父类对象:class com.jvm.classload.Parent c对象的类加载器:com.jvm.classload.MyClassLoader$1@4dc63996 myClassLoader
NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //通过classLoad 其中的classLoad也就是父类加载器,我们在这里就先证明他就是去加载class对象了。(具体不在这里细究)。
> c = classLoader.loadClass("ClassLoad.C"); // LoadClass 它只是加载了C类,但是并没有触发解析C类中的方法,因此并不会加载D类 > aClass = Class.forName("ClassLoad.F"); System.out.println(aClass.getClassLoader()); } } package ClassLoad; public class F { static { System.out.println("bootstrap F init"); ClassLoad.demo3 bootstrap F init null Xbootclasspth 表示设置 bootclasspath 其中 /a:. > aClass = Class.forName("ClassLoad.F"); System.out.println(aClass.getClassLoader()); } }
lisPresent(className, classLoader); }; public abstract boolean matches (String className, ClassLoader classLoad er); //通过类加载是否抛出异常来判断该类是否存在 public static boolean isPresent(String className, ClassLoader classLoad > forName ( String className, ClassLoader classLoad er) throws Clas sNotFoundException { if (classLoader
PS:详细得我不多说了,直接看源码把,主要理解这个思路里面有classload加载对应的class,通过spring的IOC加载bean的方式获取Advice,进行控制。