Java:由ClassLoader加载时,为类的物理字节分配的内存在哪里?

时间:2011-05-20 06:36:24

标签: java classloader

我在虚拟应用程序中构建了一个很小的自定义类加载器,以便了解动态类加载的工作原理。对于这个问题,除了提到它实例化我的类加载器的两个不同实例并且每个加载不同的类之外,我不需要详细介绍它的功能,以便通过确认“我可以满足自己”。 ClassNotFoundException“来自其中一个类加载器实例,只有另一个加载了特定的类。

但是,我有一个问题可以通过以下方式轻松表达,希望这些代码能够用不言自明的方式表达。

        Class clazz = myClassLoader.loadClass(theClazz);

这行代码导致我的自定义类加载器将类字节加载到内存中,并返回该类的Class对象的实例。

我的问题是:加载类的内存物理字节在哪里(即.class文件的内容)?它们是存储在ClassLoader对象中,还是存储在Class对象内(因此ClassLoader对象只包含对此Class对象的内部引用) - 或者完全在其他地方?< / p>

6 个答案:

答案 0 :(得分:2)

从ClassLoader的源代码:

// The classes loaded by this class loader.  The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private Vector classes = new Vector();

java类的源代码位于JDK目录的src.zip中。

编辑: 那是你问的吗?

答案 1 :(得分:2)

在最低级别,类的二进制表示存在于虚拟机的各个运行时区域中,最明显的是Method AreaRuntime Constant Pool。简单来说,方法区域应包含有关类的信息,包括方法和构造函数的代码,如虚拟机规范中的以下引用所示:

  

Java虚拟机有一个方法   所有Java共享的区域   虚拟机线程。方法   区域类似于存储区域   用于传统的编译代码   语言或类似于“文本”   UNIX进程中的段。它存储   每类结构如   运行时常量池,字段和   方法数据和方法的代码   和构造函数,包括   课堂上使用的特殊方法(§3.9)   和实例初始化和   接口类型初始化。

答案 2 :(得分:2)

classloader对象具有已加载的所有类的Collection。

如果相同的物理类由2个不同的类别的laoders加载,那么该类的字节数是memeory的两倍。这两个类的行为类似于不同的类型。它们彼此不兼容!存储字节的地方并不真实,我想知道你为什么要知道这一点。如果您编写自己的ClassLoader,您可以将它们“存储”在任何您想要的位置。但是在某些时候,您将进行如下调用:ClassLoader.defineClass(String,byte [],int,int)。然后创建VM内存中的相关结构(MethodArea,ConstantPool等),如其他答案中所述。

答案 3 :(得分:1)

  

&#34;这行代码导致我的自定义类加载器将类字节加载到内存中,并为该类返回一个Class对象的实例&#34;

如果我理解你的问题是正确的,那么对象的内存分配是在java进程的堆空间完成的。

答案 4 :(得分:1)

这取决于JVM,例如herehere。旧版本的Mac OS使用指向指针方案的指针,称为handle

答案 5 :(得分:1)

类文件及其内部的特定于JVM的表示通常存储在永久生成中 - 至少存储在JVM的Sun / Oracle版本中。

有关更多链接,请参阅What does PermGen actually stand for?