1. Foo.class 代表什么
Whenever we compile any Java file, the compiler will embed a public, static, final field named class
, of the type java.lang.Class
, in the emitted byte code. Since this field is public, we can access it using dotted notation
JVM类加载过程划分为装载,链接和初始化。装载和链接过程完成后,即将字节码转换为为Class对象。初始化过程会执行类中静态初始化代码,静态属性的初始化。
Foo.class会生成 Class 的对象,但它并没有进行初始化
Class.forName("com.hong.classLoader.Foo"会进行初始化,因为它调用的
Class<T> java.lang.Class.forName(String name, boolean initialize, ClassLoader loader)
initialize为true
让ClassLoader去装载Foo.class 字节码 返回代表Foo这个类的 Class对象
System.out.println(ClassLoaderDemo.class.hashCode()); System.out.println(Class.forName("com.hong.ClassLoaderDemo").hashCode());
System.out.println(ClassLoaderDemo.class.getClassLoader()); System.out.println(Class.forName("com.hong.ClassLoaderDemo").getClassLoader());
这两个产生的 Class对象是一样的,说明只装载一次
Class里有存加载它们的ClassLoader,加载他们的ClassLoader也是同一个
2. 为什么普通的类是被 AppClassLoader加载 ?
http://www.iteye.com/topic/83978
-----BootStrap类加载器 加载JRE/lib
-----ExtClassLoader 加载 JRE/lib/ext
-----AppClassLoader 加载ClassPath/
System.out.println(System.getProperty("sun.boot.class.path")); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(System.getProperty("java.class.path"));
3.一个相同的类被两个ClassLoader加载,有什么好处
一个Application server避免两个应用相互干扰,比如tomcat下放几个工程,tomcat启动的时候把他们启动起来用不同的ClassLoader 就不会相互干扰
JVM通过类的全限定名和类加载器来标识一个被加载的类
4.不同classloader里的类能交互吗
if class Foo is loaded by class loader B, and Foo depends on class Baz, then class Baz must be loadable by either class loader A or B. If Baz is only visible to class loader C or D, then a ClassNotFoundException will occur
5.调用static方法要创建对象吗?
不用,但要装载类,会对Class对象进行初始化
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
反射调用类的方法也会初始化
测试代码:
/** * */ package com.hong.classLoader; import java.util.Random; /** * @author Administrator * */ class Initable { static final int staticFinal = 47; static final int staticFinal2 = ClassInitialization.rand.nextInt(100); Initable() { System.out.println("Initable construct invoke"); } static { System.out.println(" Initable static invoke"); } } class Initable2 { static int staticNoFinal = 147; static { System.out.println("Initialization Initable2"); } } class Initable3 { static int staticNoFinal = 74; static { System.out.println("Initialization Initable3"); } } public class ClassInitialization { public static Random rand = new Random(47); public static void main(String[] args) throws ClassNotFoundException { Class<Initable> initable = Initable.class; // 不会引起初始化 Class<?> initable2 = Class.forName("com.hong.classLoader.Initable", false, ClassInitialization.class.getClassLoader());// 不会引起初始化 System.out.println(initable.hashCode()); System.out.println(initable2.hashCode()); System.out.println(ClassInitialization.class.getClassLoader());// classloader // 是同一个 System.out.println("after creating Initable reference"); System.out.println(Initable.staticFinal); // 引用编译期常量不会引起初始化 System.out.println(Initable.staticFinal2); // 引起初始化 System.out.println(Initable2.staticNoFinal); // 引用非编译期常量会引起初始化 Class initable3 = Class.forName("com.hong.classLoader.Initable3"); // 默认会引起初始化 System.out.println("after creating Initable3 reference"); System.out.println(Initable3.staticNoFinal);// 前面已经初始化此处不用再初始化 } }
参考:http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44459
http://onjava.com/pub/a/onjava/2005/01/26/classloading.html?page=1