//最常用的加载类的方法。 public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } //核心的类加载方法,这里面有递归实现双亲委派 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) {//获取锁,保证并发安全 //首先先判断这个类是是否已经被加载,一般在递归时候是看父类是不是加载过这个类 Class<?> c = findLoadedClass(name); if (c == null) {//如果类没有被加载,去加载类 long t0 = System.nanoTime(); try { if (parent != null) {//如果父类加载器不为空,让父类加载器去加载这个类 c = parent.loadClass(name, false); } else {//如果没有父类加载器,说明是启动类加载器。这也是递归的尽头,使用启动类加载器去加载 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } //如果父类加载器没有加载到 if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); //调用findClass方法去加载类
// this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } //是否调用resolveClass方法。默认是不调用的。这个我们后面来介绍 if (resolve) { resolveClass(c); } return c; } } /** * 返回一个启动类加载器,如果没有返回null */ private Class<?> findBootstrapClassOrNull(String name){ //校验类的名字,如果校验失败,直接返回null if (!checkName(name)) returnnull; //调用findBootstrapClass方法返回启动类加载器 return findBootstrapClass(name); }
// return null if not found,本地方法,如果找到返回,否者返回null privatenative Class<?> findBootstrapClass(String name);
// true if the name is null or has the potential to be a valid binary name privatebooleancheckName(String name){ //校验类名字 如果ture返回null if ((name == null) || (name.length() == 0)) //判断明是是不是null,或者是空,如果是直接返回,然后返回null returntrue; //判断是不是二进制文件,结尾是-1(EOF标志),是否允许数组的语法同时是字符串形式的数组即["aaa","bbb"]。他的第一个字符是不是[,如果是说明校验通过。VM.allowArraySyntax是JVM的一个配置属性。一般是ture或false if ((name.indexOf('/') != -1)|| (!VM.allowArraySyntax() && (name.charAt(0) == '['))) returnfalse; returntrue; }
/** * 重写父类方法,返回一个Class对象 * ClassLoader中对于这个方法的注释是: * This method should be overridden by class loader implementations */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException {
Class clazz = null; String classFilename = name + ".class"; System.out.println(classFilename); File classFile = new File(classFilename); if (classFile.exists()) { try (FileChannel fileChannel = new FileInputStream(classFile) .getChannel();) { MappedByteBuffer mappedByteBuffer = fileChannel .map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); byte[] b = mappedByteBuffer.array(); clazz = defineClass(name, b, 0, b.length); } catch (IOException e) { e.printStackTrace(); } } if (clazz == null) { thrownew ClassNotFoundException(name); } return clazz; }