标签:传递 运行时 数组 generate 它的 失败 tst size tput
加载-》验证-》准备-》解析-》初始化-》使用-》卸载
类加载包括以上的前五个过程:加载,验证,准备,解析,初始化
1、主要完成三个工作
2、获取二进制字节流文件的途径
验证类是合理可用的
1、文件格式验证:验证Class文件格式是否符合规范和是否能够被当前版本虚拟机解释
2、元数据验证:对类的元数据进行语义验证,确保元数据没有不符合java语义规范
3、字节码验证:对类的方法体进行验证,
4、符号引用验证:验证符号引用是否能够正确解析
在方法区中为类变量分配内存,并赋予系统默认初始值,指0,null这种而不是代码中手工赋予的初始值
将符号应用替换成直接引用
1、调用new、getststic,putstatic,invokestatic(读取或设置静态变量,调用静态方法)
2、通过反射实例化
3、初始化子类时,若父类还没有被初始化,则要先初始化父类
4、虚拟机启动时,加载包含Main的主类
1、子类引用父类的静态字段,不会初始化子类
2、初始化数组类,不会初始化该类
3、常量在编译阶段就会读到常量缓冲池中,读取类的常量不会引起类的初始化
类加载器的作用就是根据类的全限定名称获取相对应的Class二进制字节流文件,并将其加载到虚拟机内部
意义:任何一个类的唯一性是由类本身和加载该类的类加载器一起确定的
(两个类相等,包括类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果为 true,也包括使用 instanceof 关键字做对象所属关系判定结果为 true。)
从虚拟机内部看
从开发人员角度看
一个类加载器接到了加载类的请求,并不会立即加载,而是传递给它的上层类加载器,若上次类加载器无法加载,才会尝试自己加载
使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。
例如 java.lang.Object 存放在 rt.jar 中,如果编写另外一个 java.lang.Object 并放到 ClassPath 中,程序可以编译通过。
由于双亲委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 优先级更高,
这是因为 rt.jar 中的 Object 使用的是启动类加载器,而 ClassPath 中的 Object 使用的是应用程序类加载器。
rt.jar 中的 Object 优先级更高,那么程序中所有的 Object 都是这个 Object。
loadClass() 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 ClassNotFoundException,此时尝试自己去加载。
1 public abstract class ClassLoader { 2 // The parent class loader for delegation 3 private final ClassLoader parent; 4 5 public Class<?> loadClass(String name) throws ClassNotFoundException { 6 return loadClass(name, false); 7 } 8 9 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 10 synchronized (getClassLoadingLock(name)) { 11 // First, check if the class has already been loaded 12 Class<?> c = findLoadedClass(name); 13 if (c == null) { 14 try { 15 if (parent != null) { 16 c = parent.loadClass(name, false); 17 } else { 18 c = findBootstrapClassOrNull(name); 19 } 20 } catch (ClassNotFoundException e) { 21 // ClassNotFoundException thrown if class not found 22 // from the non-null parent class loader 23 } 24 25 if (c == null) { 26 // If still not found, then invoke findClass in order 27 // to find the class. 28 c = findClass(name); 29 } 30 } 31 if (resolve) { 32 resolveClass(c); 33 } 34 return c; 35 } 36 } 37 38 protected Class<?> findClass(String name) throws ClassNotFoundException { 39 throw new ClassNotFoundException(name); 40 } 41 }
1、继承java.lang.ClassLoader
2、不用重写loadClass方法,但是需要重写findClass方法
1 public class FileSystemClassLoader extends ClassLoader { 2 3 private String rootDir; 4 5 public FileSystemClassLoader(String rootDir) { 6 this.rootDir = rootDir; 7 } 8 9 protected Class<?> findClass(String name) throws ClassNotFoundException { 10 byte[] classData = getClassData(name); 11 if (classData == null) { 12 throw new ClassNotFoundException(); 13 } else { 14 return defineClass(name, classData, 0, classData.length); 15 } 16 } 17 18 private byte[] getClassData(String className) { 19 String path = classNameToPath(className); 20 try { 21 InputStream ins = new FileInputStream(path); 22 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 23 int bufferSize = 4096; 24 byte[] buffer = new byte[bufferSize]; 25 int bytesNumRead; 26 while ((bytesNumRead = ins.read(buffer)) != -1) { 27 baos.write(buffer, 0, bytesNumRead); 28 } 29 return baos.toByteArray(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 return null; 34 } 35 36 private String classNameToPath(String className) { 37 return rootDir + File.separatorChar 38 + className.replace(‘.‘, File.separatorChar) + ".class"; 39 } 40 }
标签:传递 运行时 数组 generate 它的 失败 tst size tput
原文地址:https://www.cnblogs.com/huanglf714/p/11028439.html