Java 类的装载过程
查看Java load class 的信息:
java -verbose:class MyClass
测试代码
public class MyTest{
public static void main(String args[]) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
Class cla = Class
.forName("A", true, CRCCheckSum.class.getClassLoader());
System.out.println("After Class.forName(). Before class.newInstance()");
cla.newInstance();
new A();
Class.forName("A"); // find class A ,skip load
}
}
class A {
public A() {
System.out.println("public A() Constructor");
}
static {
System.out.println("static Code");
}
{ System.out.println("non static Code");
}
}
输出:
static Code
After Class.forName(). Before class.newInstance()
non static Code
public A() Constructor
non static Code
public A() Constructor
我的理解:
让Java加载类有三种情况,
1.直接new ,如:new MyClass();
2.Class.forName, 如:Class.forName ("org.gjt.mm.mysql .Driver")
3.定义ClassLoader,用其loadClass方法.
JVM加载一个未加载过的类分几步:
a.装载 b.连接 c.初始化 d.实例化
对于1.直接就abcd连着执行了
对于2.其有两个方法可以选择是ab,还是abc.
对于3.如果改变实现似乎可以控制到a,和ab.
1就不分析了.
对于2
有两个方法:
1)Class.forName(String className)
2)Class.forName(forName (String name, boolean initialize, ClassLoader loader)
后者的initialize参数是指名,是否需要在装载连接完毕类后,进行初始化的工作.也就是执行static代码等.
如果Class.forName("MyClass") 则相当于:Class.forName("MyClass",true,this.getClass.getClassLoder());
这个也就是为什么要用
Class.forName("com.mysql.jdbc.Driver" ); 来注册driver
因为com.mysql.jdbc.Driver中有这样的代码:
public class Driver extends NonRegisteringDriver
{
public Driver() throws SQLException
{ }
static
{
try {
DriverManager.registerDriver(new Driver());
}
catch(SQLException E) {
throw new RuntimeException("Can't register driver!");
}}}
这样调用,由于在Class.forName进行加载的时候会自动执行初始化,也就是想DriverManager注册自己.
所以就不必再用newInstance()来生成一个实例.
对于3.有这样两个方法
ClassLoader.loadClass(String className);
protected ClassLoader.loadClass(String className,boolean resolve);
关于resolve的行为还不太懂,改天继续写.
classLoder 层次:
bootstrap classloader
|
extension classloader
|
system classloader
获得bootstrap classLoader加载哪些内容:
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toString());
}
获得SystemClassLoader(): ClassLoader.getSystemClassLoader()
获得ExtensionClassLoader():ClassLoader.getSystem.ClassLoader().getParent();
参考文章:
http://www.iteye.com/topic/25053
http://www.iteye.com/topic/189897
http://www.iteye.com/topic/11003
http://www.iteye.com/topic/12084
http://www.iteye.com/topic/68170
http://www.iteye.com/topic/70217