jvm类加载器如何加载在另一个类中定义的类?

时间:2014-06-11 07:41:56

标签: jvm classloader inner-classes

JVM如何加载在另一个类中定义的类?

示例:假设有一个在A类中定义的B类

package test.sample;
    Class A {
         // some instructions

         Class B {
             // few more instructions
         }
    }

在这种情况下,

  1. classloader如何加载B类? (即,它如何识别B类?)
  2. B类的完全限定名称是什么?

1 个答案:

答案 0 :(得分:1)

内部类是Java语言功能,而不是JVM功能。也就是说,Java编译器" flatten"类结构,因此JVM只能看到常规类,通常名称中包含$。在这种情况下,会有类test.sample.Atest.sample.A$B(后者是B的完全限定名称)。匿名内部类获得编译器定义的名称,例如,通常从1开始并向上计数:test.sample.A$6。编译器可以添加名称为access$200的方法,以允许封闭类和内部类相互访问'私人会员。 (请注意,$在用户定义的类和方法名称中是合法的,但是不鼓励,因此名称中$的存在并不意味着它是由编译器生成的;为此,有&# 39; s Synthetic attribute和ACC_SYNTHETIC修饰符位,通过Class.isSynthetic()等方法反射出来。)

JVM像任何其他类一样加载这些类,通常在某些JAR文件中查找文件test/sample/A$B.class,但也可能在网络中加载它们,使用字节码操作库即时生成它们等等。

当生成引用内部类(defining, containing, or simply using)的类文件时,Java编译器会发出指定包含关系的InnerClasses属性,以帮助单独编译和反射(Class.getDeclaringClass() and Class.getEnclosingClass())。方法内定义的类的类文件还包含一个EnclosingMethod属性,引用封闭方法,用于反射(Class.getEnclosingMethod()和Class.getEnclosingConstructor())。但是,这些属性仅在加载和链接期间由JVM检查语法的良好格式;在实际调用反射方法之前,不会报告不一致性。