在Java中,类通过特殊的对象——类加载器(class loaders)加载到内存中。每个类加载器形成自己独特的类可见性空间。
类加载器的类型:
$JAVA_HOME/lib/ext加载扩展。特点:
可以在JVM进程中加载同一类的多个版本吗,如何做到这一点?
**答案:**可以,如果使用不同的类加载器。用不同加载器加载的具有相同FQDN的类被认为是JVM中的不同类型。
示例:
ClassLoader loader1 = new URLClassLoader(new URL[]{...}); ClassLoader loader2 = new URLClassLoader(new URL[]{...}); Class clazz1 = loader1.loadClass("com.example.MyClass"); Class clazz2 = loader2.loadClass("com.example.MyClass"); System.out.println(clazz1 == clazz2); // false
故事
在一个大型服务器系统中使用插件,每个插件通过独立的自定义类加载器连接。插件通过公共接口进行对象交换,该接口也由其自己的类加载器加载。在进行类型转换时会发生ClassCastException,因为插件的接口'PluginApi'与主系统的接口被视为不同类型。
故事
通过自定义类加载器尝试“热”重新加载servlet导致内存泄漏——旧类未从内存中卸载,因为在静态变量中保留了某个引用。结果,PermGen迅速溢出。
故事
一款支持动态加载模块的产品不明确使用系统类加载器,开发人员意外替换了其父加载器,导致无法访问基础类(例如JDK中的类)。这在新模块无法加载标准Java类(例如
java.sql.Driver)时表现为崩溃。