标签:
1.关于“类加载器”和“生成的这个Class对象”:
1)类加载器
Bootstrap Loader(启动类加载器)、Extended Loader(标准扩展类加载器ExtClassLoader)、AppClass Loader(系统类加载器/应用程序类加载器AppClassLoader)
启动类加载器:
目的:加载java_home\lib目录下的字节码文件(如:rt.jar,含有java.lang.Object等基本类) 具体有哪些文件及加载顺序?
方式:加载System.getProperty("sun.boot.class.path")所指定的路径或jar,在使用Java运行程序时,也可以指定其搜索路径,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld 参考:http://www.cnblogs.com/ITtangtang/p/3978102.htm
标准扩展类加载器:
目的:加载java_home\lib\ext目录下的字节码文件
方式:加载System.getProperty("java.ext.dirs")所指定的路径或jar。在使用Java运行程序时,也可以指定其搜索路径,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld
结果:<实现类>sun.misc.Luncher@ExtClassLoader————————<继承关系>ClassLoader>URLClassLoader>AppClassLoader
应用程序类加载器:
方式:加载System.getProperty("java.class.path")所指定的路径或jar。在使用Java运行程序时,也可以加上-cp来覆盖原有的Classpath设置,例如: java -cp ./lavasoft/classesHelloWorld
结果:<实现类>sun.misc.Luncher@AppClassLoader————————<继承关系>ClassLoader>URLClassLoader>AppClassLoader
自定义类加载器:
方式:1)继承java.lang.ClassLoader并重写loadClass方法;2)继承java.lang.ClassLoader并重写findClass方法/**JDK1.2后推荐,原因见下方红色部分*/;
相关:
1 <一>java.lang.Object 2 1.getClass() 3 public final native Class<?> getClass(); //拿到运行时的Class对象【通过本地方法】 4 /** 5 *例子:class-Test>main> 6 * Class c =Person.getClass(); 7 */ 8 /** 9 *实现: 10 *1)虚拟机启动 11 *2)虚拟机类加载——Test.class————加载阶段:方法区>外部接口>new java.lang.Class //Class<?> 12 *3)虚拟机类加载——java.lang.Object————【Test加载阶段】触发 13 *3)虚拟机类加载——Person.class ————【Test加载阶段】触发 14 *4)应用程序启动 15 *5)调用java.lang.ClassLoader>xxx1()、xxx2().....——返回运行时<Person>Class对象 16 */ 17 18 19 <二>java。lang.ClassLoader 20 1.loadClass(String name, boolean resolve) /**加载指定名称(包括包名)的二进制类型,同时指定是否解析*/ 21 loadClass(String name) 22 protected Class<?> findClass(String name) throws ClassNotFoundException { //空方法 23 throw new ClassNotFoundException(name); 24 } 25 protected Class<?> loadClass(String name, boolean resolve) //拿到类加载器【通过本地方法】 26 throws ClassNotFoundException 27 { 28 synchronized (getClassLoadingLock(name)) { 29 // First, check if the class has already been loaded 30 Class c = findLoadedClass(name); 31 if (c == null) { 32 long t0 = System.nanoTime(); 33 try { 34 if (parent != null) { 35 c = parent.loadClass(name, false); 36 } else { 37 c = findBootstrapClassOrNull(name); 38 } 39 } catch (ClassNotFoundException e) { 40 // ClassNotFoundException thrown if class not found 41 // from the non-null parent class loader 42 } 43 44 if (c == null) { 45 // If still not found, then invoke findClass in order 46 // to find the class. 47 long t1 = System.nanoTime(); 48 c = findClass(name); 49 50 // this is the defining class loader; record the stats 51 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); 52 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); 53 sun.misc.PerfCounter.getFindClasses().increment(); 54 } 55 } 56 if (resolve) { 57 resolveClass(c); 58 } 59 return c; 60 } 61 } 62 63 64 65 66 <三>java.lang.Class 67 1.getClassLoader() 68 /**例子:class-Test>main> 69 * Object o =new Object(); 70 * System.out.println(o.getClass().getClassLoader()); 71 结果>java.lang.NullPointerException 72 */ 73 /** 74 *Returns the class loader for the class. 75 *This method will return null in such implementations if this class was loaded by the bootstrap class loader. 76 *如果没有指定classLoader就默认返回bootstrap classLoader(启动类加载器),因为这个bootstrap classLoader 77 *用户拿不到实例,所以返回null表示返回的是bootstrap classLoader 78 */ 79 native ClassLoader getClassLoader0(); //拿到类加载器【通过本地方法】 80 public ClassLoader getClassLoader() { 81 ClassLoader cl = getClassLoader0(); 82 if (cl == null) 83 return null; 84 SecurityManager sm = System.getSecurityManager(); 85 if (sm != null) { 86 ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); 87 } 88 return cl; 89 }
2.指定类加载器加载类
Class.forName(name, initialize, loader)
2)与“生成的Class对象”关系
同一Class文件只有被同一类加载器加载,才能判断为相等————>相等的意义在于:1)不相等,会生成多个Class对象;相等,只会生成一个Class对象
2) 只有同一个Class对象,equals()、isAssignabaleFrom()、instanceof、isInstance()返回结果才相同;
3)双亲委派模型
关系?
上一级持有下一级的一个引用,属于 has A关系
分工?(为什么叫双亲委派)
一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给上一层的类加载器去完成。只有当上级加载器在搜索范围找不到所需类,无法完成这个加载请求时,下级加载器才会尝试自己去加载
好处?
Java类随着它的类加载器一起具备了一种优先级的层次关系
2.加载“类/接口”的策略:
非数组类/接口、数组类(组件类型为基本类型,如int[][]):
加载生成代表这个类的java.lang.Class对象后,将在类加载器的“类名称空间”上标识为“已加载”(因为前面已经讨论了,同一Class文件对应同一个类加载器才确定生成的是同一个Class对象)
连接阶段:
验证——文件格式、元数据、字节码
准备——在方法区为类变量分配内存并初始化
例子 编译时期 (类加载时)验证阶段—准备时期
static int i =20; 产生constantValue属性,但不会存入常量20 常规方式进行准备:初始化、分配内存
结果—————> 无 0
final static int i =20; 产生constantValue属性,并存20到constantValue 从对应constantValue取出来初始化
结果—————> 20 20
解析——将运行时常量池的符号引用替换为直接引用(指向内存目标的句柄),这一过程又叫“静态绑定/静态连接”
1 //例子(笔试常考题目) 2 public class Father { 3 4 private static int i =20; 5 static{ 6 System.out.println("Father;(类构造器-before)"+i); 7 i =50; 8 System.out.println("Father;(类构造器-after)"+i); 9 } 10 public Father() { 11 System.out.println("Father:(实例构造器)"+i);13 } 14 15 } 16 17 18 19 public class Son extends Father{ 20 21 private static int i =20; 22 static{ 23 System.out.println("Son;(类构造器-before)"+i); 24 i =50; 25 System.out.println("Son;(类构造器-after)"+i); 26 } 27 public Son() { 28 System.out.println("Son:(实例构造器)"+i); 30 } 31 } 32 33 34 35 public class Main { 36 37 public static void main(String[] args) { 38 new Son(); 39 40 } 41 42 } 43 44 //输出结果: 45 /** 46 *Father;(类构造器-before)20 47 *Father;(类构造器-after)50 48 *Son;(类构造器-before)20 49 *Son;(类构造器-after)50 50 *Father:(实例构造器)50 51 *Son:(实例构造器)50 52 */
读《深入理解Java虚拟机》有感——第二部分:虚拟机类加载机制
标签:
原文地址:http://www.cnblogs.com/crazyYouth/p/5397781.html