Java 动态加载
来源:互联网 发布:大额淘宝优惠券哪里领 编辑:程序博客网 时间:2024/05/16 04:27
以上三个路径都是Java的系统属性,可以通过System.getProperty(String key)方法来查看其设置:
System.out.println(System.getProperty("java.class.path"));
现在看看每一种属性输出后的值,从而可以发现每种Class Loader分别负责哪些类的装载:
key: sun.boot.class.pathString: %JAVA_HOME%/lib/resources.jar, rt.jar, sunrsasign.jar, jsse.jar, jce.jar, charsets.jar, %JAVA_HOME%/classes key: java.ext.dirsString: %JAVA_HOME%/lib/ext, %Windows%/sun/java/lib/ext key: java.class.path
- 检查这个类是否已经被加载进去了
- 如果还没有加载,调用父对象加载该类
- 如果父对象无法加载,调用本对象的findClass()取得这个类。
因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写自己的ClassLoader,可以
- 在执行非置信代码之前,自动验证数字签名
- 动态地创建符合用户特定需要的定制化构建类
- 从特定的场所取得java class,例如数据库和网络。
当创建自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对 象时,需要指定一个父对象;如果没有的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。
Class foo = Class.forName(String ClassTypeName); // 通过调用ClassLoa der.getCallerClassLoader( )得到当前Class Loader,然后查找并载入ClassTypeName。orClass foo = Class.forName(String ClassTypeName, boolean initialize, ClassLoader loader) // 显式指定用哪个Class Loader来查找并载入ClassTypeName。 ClassTypeName boo = (ClassTypeName) foo.newInstance( );
ClassLoader foo = Thread.currentTread().getCoontextClassLoader();第五部分: Class.forName()与ClassLoader.loadClass()的区别
Class clazz = Class.forName("XXX.XXX");与
ClassLoader cl = Thread.currentThread().getContextClassLoader();Class clazz = cl.loadClass("XXX.XXX");都可以装载一个类那么他们的区别是什么呢?
进一步研究Class.forName()是调用
Class.forName(name, initialize, loader); 也就是Class.forName("XXX.XXX"); 等同与 Class.forName("XXX.XXX", true, CALLCLASS.class.getClassLoader());
第二次参数表示装载类的时候是否初始化该类, 即调用类的静态块的语句及初始化静态成员变量。
Class clazz = cl.loadClass("XXX.XXX"); 没有指定是否初始化的选项。只有执行clazz.newInstance();时才能够初始化类。可以说 Class.forName("XXX.XXX", false, cl)执行过程是一致的。只是ClassLoader.loadClass()是更底 层的操作。
看一下JDBC驱动的装载。
Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbcurl");当调用Class.forName("com.mysql.jdbc.Driver");是Driver已经被初始化并注册到DriverManager中。MySQL Driver的代码public class Driver extends NonRegisteringDriverimplements java.sql.Driver{public Driver()throws SQLException{}static {try{DriverManager.registerDriver(new Driver());}catch(SQLException E){throw new RuntimeException("Can't register driver!");}}}改修JDBC驱动的装载
ClassLoader cl = Thread.currentThread().getContextClassLoader();Class clazz = cl.loadClass("com.mysql.jdbc.Driver");clazz.newInstance();Connection conn = DriverManager.getConnection("jdbcurl");同样可以执行。
进一步说:
Class .forName是从指定的classloader中装载类,如果没有指定,也就是一个参数的时候,是从装载当前对象实例所在的classloader中装载类.
而ClassLoader的实例调用loadclass方法,是指从当前ClassLoader实例中调用类,而这个实例与装载当前所在类实例的Classloader也许不是同一个 .
举个例子吧, 有A,B , C两个ClassLoader , 当前运行的类D的实例是d(装载它的是A) , 如果D中使用Class .forName那么就是使用的ClassLoader就是A,当然,也可以指定为B. 而如果D中代码找到的ClassLoader实例是C,那么就是用D来装载所指定的类.
为什么要用不同的ClassLoader 装载?
举例来说:如果在Class 被载入的过程中,你希望使用在自己的Class Loader来实现特定的操作,请使用ClassLoader方式。
貌似CGLib之类的bytecode generation框架很多地方会使用指定特殊ClassLoader的方式。
使用多个classloader的情况非常常见,比如说我们的app server,那么都是这样的. 在Web与EJB间, 他们的classLoader就是不同的,这样做的目的就是为了避免两者间类装载的相互干扰.
再举个例子:
Static初始化区块在什么时候被调用的问题?
Public A{Static{System.out.println(“HaHaHa”);}}Class.forName(“A”);Class.forName(“A”,false, ClassLoader.getSystemClassLoader());看看奥妙在哪里?Java ClassLoader机制和原理又是如何?
程序示例:
public class A {static { System.out.println("A`static is executed!");}public A() {System.out.println("A`construct is executed!");}public void show(){System.out.println("A`method is executed!");}}调用程序1:
Class c = Class.forName("A");Method m = c.getMethod("show", new Class[0]);System.out.println("A`test is executed!");Object obj = c.newInstance();m.invoke(obj, new Object[0]);执行结果:
A`static is executed!
A`test is executed!
A`construct is executed!
A`method is executed!
调用程序2:
Class c = ClassLoader.getSystemClassLoader().loadClass("A");System.out.println("A`test is executed!");Method m = c.getMethod("show", new Class[0]);Object obj = c.newInstance();m.invoke(obj, new Object[0]);执行结果:
A`test is executed!
A`static is executed!
A`construct is executed!
A`method is executed!
可见执行顺序为先执行 static{}块中的代码,然后执行构造函数,之后才是方法的调用。
classloader的两种载入方式:
1)pre-loading预先载入,载入基础 类
2)load-on-demand按需求载入
java动态载入class的两种方式:
1)implic it隐式,即利用实例化才载入的特性来动态载入class
2)explic it显式方式,又分两种方式:
a)java.lang.Class的forName()方法 (上述调用程序1采用此方式载入)
b)java.lang.ClassLoader的loadClass()方法(上述调用程序2采用此方式载入)
static块在什么时候执行?
当调用forName(String)载入class时执行,( 这个过程在类的所有父类中递归地调用)
如果调用ClassLoader.loadClass并不会执行.
forName(String,false,ClassLoader)时也不会执行.
如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作
static块仅执行一次
- java动态加载类
- JAVA 动态加载
- java 动态加载类
- Java 动态加载类
- Java 动态加载
- java classLoader动态加载
- java classLoader动态加载
- java动态加载类
- Java动态类加载
- Java动态加载jar
- Java动态类加载
- java动态加载配置文件
- Java 动态加载
- Java 动态加载
- Java动态类加载
- Java 动态加载
- java动态加载配置文件
- java 动态加载机制
- android:configChanges
- 线程安全的Java类
- 二叉树
- 2016年3月装修日志
- MSRDS机器人仿真软件学习资源汇总
- Java 动态加载
- POJ 1459
- 类似于StringBuilder的字符串加强处理类
- Delaunay三角剖分(Delaunay Triangulation)相关知识
- 序列化与反序列化
- Python 进阶——从 list 到 NumPy 的多维数组
- 分治法求整数相乘
- python中pip的安装
- 登录itunes store输入"a0a36b00ba2f45918ad6025446a6d0cd"账户的apple id密码