[讨论] 关于GeneratedMethodAccessor的一点疑问

巴海和 2014-07-31
在OpenJDK 6下反射调用生成的”GeneratedMethodAccessor+数字“类是由JVM直接生成到内存里?还是需要通过Java层次的类加载器进行加载?如果通过类加载器进行加载的话,是通过哪个类加载器呀?
我已经阅读过这两篇文章了,只是还有上述疑问,求解答,3ks。
http://rednaxelafx.iteye.com/blog/548536
http://rednaxelafx.iteye.com/blog/727938
nijiaben 2014-07-31
巴海和 写道
在OpenJDK 6下反射调用生成的”GeneratedMethodAccessor+数字“类是由JVM直接生成到内存里?还是需要通过JAVA层次的类加载器进行加载?如果通过类加载器进行加载的话,是通过哪个类加载器呀?
我已经阅读过这两篇文章了,只是还有上述疑问,求解答,3ks。
http://rednaxelafx.iteye.com/blog/548536
http://rednaxelafx.iteye.com/blog/727938


通过method的定义类加载器加载的,
详情见
private MagicAccessorImpl generate(final Class declaringClass,
                                       String name,
                                       Class[] parameterTypes,
                                       Class   returnType,
                                       Class[] checkedExceptions,
                                       int modifiers,
                                       boolean isConstructor,
                                       boolean forSerialization,
                                       Class serializationTargetClass)
{
//class字节码构建过程略

 return AccessController.doPrivileged(
            new PrivilegedAction<MagicAccessorImpl>() {
                public MagicAccessorImpl run() {
                        try {
                        return (MagicAccessorImpl)
                        ClassDefiner.defineClass
                                (generatedName,
                                 bytes,
                                 0,
                                 bytes.length,
                                 declaringClass.getClassLoader()).newInstance();
                        } catch (InstantiationException e) {
                            throw (InternalError)
                                new InternalError().initCause(e);
                        } catch (IllegalAccessException e) {
                            throw (InternalError)
                                new InternalError().initCause(e);
                        }
                    }
                });
}


其中declaringClass.getClassLoader()就是method的定义类的类加载器
static Class defineClass(String name, byte[] bytes, int off, int len,
                             final ClassLoader parentClassLoader)
    {
        ClassLoader newLoader = AccessController.doPrivileged(
            new PrivilegedAction<ClassLoader>() {
                public ClassLoader run() {
                        return new DelegatingClassLoader(parentClassLoader);
                    }
                });
        return unsafe.defineClass(name, bytes, off, len, newLoader, null);
    }

实则通过unsafe.defineClass来定义类,类的字节流已经有了,直接传到了jvm里的如下方法进行类的定义
klassOop SystemDictionary::resolve_from_stream(Symbol* class_name,
                                               Handle class_loader,
                                               Handle protection_domain,
                                               ClassFileStream* st,
                                               bool verify,
                                               TRAPS)

而上述的class_loader就是上面的defineClass返回的DelegatingClassLoader对象,但是在jvm里会使用代理的parentClassLoader来进行类定义
oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
  if (loader != NULL) {
    // See whether this is one of the class loaders associated with
    // the generated bytecodes for reflection, and if so, "magically"
    // delegate to its parent to prevent class loading from occurring
    // in places where applications using reflection didn't expect it.
    klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass();
    // This might be null in non-1.4 JDKs
    if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
      return parent(loader);
    }
  }
  return loader;
}
巴海和 2014-08-01
nijiaben 写道
巴海和 写道
在OpenJDK 6下反射调用生成的”GeneratedMethodAccessor+数字“类是由JVM直接生成到内存里?还是需要通过JAVA层次的类加载器进行加载?如果通过类加载器进行加载的话,是通过哪个类加载器呀?
我已经阅读过这两篇文章了,只是还有上述疑问,求解答,3ks。
http://rednaxelafx.iteye.com/blog/548536
http://rednaxelafx.iteye.com/blog/727938


通过method的定义类加载器加载的,
详情见
private MagicAccessorImpl generate(final Class declaringClass,
                                       String name,
                                       Class[] parameterTypes,
                                       Class   returnType,
                                       Class[] checkedExceptions,
                                       int modifiers,
                                       boolean isConstructor,
                                       boolean forSerialization,
                                       Class serializationTargetClass)
{
//class字节码构建过程略

 return AccessController.doPrivileged(
            new PrivilegedAction<MagicAccessorImpl>() {
                public MagicAccessorImpl run() {
                        try {
                        return (MagicAccessorImpl)
                        ClassDefiner.defineClass
                                (generatedName,
                                 bytes,
                                 0,
                                 bytes.length,
                                 declaringClass.getClassLoader()).newInstance();
                        } catch (InstantiationException e) {
                            throw (InternalError)
                                new InternalError().initCause(e);
                        } catch (IllegalAccessException e) {
                            throw (InternalError)
                                new InternalError().initCause(e);
                        }
                    }
                });
}


其中declaringClass.getClassLoader()就是method的定义类的类加载器
static Class defineClass(String name, byte[] bytes, int off, int len,
                             final ClassLoader parentClassLoader)
    {
        ClassLoader newLoader = AccessController.doPrivileged(
            new PrivilegedAction<ClassLoader>() {
                public ClassLoader run() {
                        return new DelegatingClassLoader(parentClassLoader);
                    }
                });
        return unsafe.defineClass(name, bytes, off, len, newLoader, null);
    }

实则通过unsafe.defineClass来定义类,类的字节流已经有了,直接传到了jvm里的如下方法进行类的定义
klassOop SystemDictionary::resolve_from_stream(Symbol* class_name,
                                               Handle class_loader,
                                               Handle protection_domain,
                                               ClassFileStream* st,
                                               bool verify,
                                               TRAPS)

而上述的class_loader就是上面的defineClass返回的DelegatingClassLoader对象,但是在jvm里会使用代理的parentClassLoader来进行类定义
oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
  if (loader != NULL) {
    // See whether this is one of the class loaders associated with
    // the generated bytecodes for reflection, and if so, "magically"
    // delegate to its parent to prevent class loading from occurring
    // in places where applications using reflection didn't expect it.
    klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass();
    // This might be null in non-1.4 JDKs
    if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
      return parent(loader);
    }
  }
  return loader;
}

method的定义类的类加载器是从哪里来的?另外,您的意思是上述生成的类是直接由JVM使用对应的字节流在内存里展开?不需要经过类加载器进行加载?3ks
nijiaben 2014-08-01
巴海和 写道

method的定义类的类加载器是从哪里来的?


你当初获取method的时候不是通过class得到的吗,每个class都有一个定义类加载器,也就是在那个classloader的classpath里是存在那个类的(当然也可能动态创建,类似反射的这种情况)

巴海和 写道

另外,您的意思是上述生成的类是直接由JVM使用对应的字节流在内存里展开?不需要经过类加载器进行加载?3ks

字节流在java层面构建,直接走jvm里通过字节流定义类的方法,并不需要走java层面的类加载器的loadClass方法来获取字节码流
Global site tag (gtag.js) - Google Analytics