java基础类加载学习笔记

(部分内容系转载 )

Java中一共有四个类加载器,之所以叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存。
这四个类加载器分别为:Bootstrap ClassLoaderExtension ClassLoaderAppClassLoader
URLClassLoader,他们的作用其实从名字就可以大概推测出来了。其中AppClassLoader在很多地方被叫做System ClassLoader

Bootstrap ClassLoader是在JVM开始运行的时候加载java的核心类,是用C++编写的,它用来加载核心类库,在JVM源代码中这样写道:
static const char classpathFormat[] =
"%/lib/rt.jar:"
"%/lib/i18n.jar:"
"%/lib/sunrsasign.jar:"
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/classes";
Extension ClassLoader是用来加载扩展类,即/lib/ext中的类。
AppClassLoader用来加载Classpath的类,是和我们关系最密切的类。


URLClassLoader:在javaweb项目中经常用到通过xml来配置使用的类,如tomcat体系中就需要根据xml加载指定servlet类。此时就要使用到URLClassLoader,这个类是如何工作的?

测试代码使用了一个inter接口,在项目工程的路径中没有提供实现类,而自定义了一个实现类并打包在ForLoad.jar文件中:  

 1 public class Test {
 2 
 3 public static void main(String[] args) throws IOException {
 4   URL[] urls = new URL[1];
 5   File file = new File("D:\\ForLoad.jar");
 6   System.out.println(file.exists());
 7   URLClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()});
 8   try {
 9     Class<inter> forLoadClazz = (Class<inter>) loader.loadClass("classload.Forload");
10     inter inter = (inter) forLoadClazz.newInstance();
11     inter.invoke();
12   } catch (ClassNotFoundException e) {
13     e.printStackTrace();
14   } catch (InstantiationException e) {
15     e.printStackTrace();
16   } catch (IllegalAccessException e) {
17     e.printStackTrace();
18   }
19   }
20 }

代码非常简单,可以看到第11行顺利执行了,说明实现类被顺利加载到。

这里有两个细节要注意:

1.ForLoad.jar必须正确打包,目录结构要按照类的路径来设置,否则抛出ClassNotFoundException,
2.loadClass这里要写全限定名
 
类加载的双亲委派模型
  当前classpath下如果有classload.Forload 的话,会去加载这个类,而不是url指定位置的那个类
为什么呢?以下是ClassLoader的 loadClass实现:
  
  
   发现首先去要求父加载器去加载类,只有当父亲加载不到的时候,才去调用自己的findClass方法。这样就可以解释了,因为夫加载器顺利加载到了类路径下的那个类,就屏蔽了URLClassLoader的作用。
  这么做是为什么呢?百度了一下发现,主要是java类加载为了安全考虑,防止重要类被hack:如Object,String这些类如果有被替换实现的话,会导致不可预计的结果。熟悉攻击的就知道,unix环境下黑客重要的一招就是通过获取到root之后替换某些命令的含义。
原文地址:https://www.cnblogs.com/violinn/p/3106025.html