英文:
CompilingClassLoader fun, any ideas how child class loads from different classloader in this case?
问题
在线 29 的堆栈跟踪下的 createController 方法中的代码如下,clazz.getClasslo
protected Object createController(Injector injector, String controllerClassFullName) {
Class<?> clazz = classLoader.clazzForName(controllerClassFullName);
return injector.getInstance(clazz); //line 29!!!!
}
在线 521 的 loadClass 正在加载上述 'clazz' 变量的构造函数所在的类,但没有从 CompilingClassLoader 加载。它以某种方式跳过了它。构造函数有三个参数,除了最后一个参数外,其余参数都从 CompilingClassLoader 加载:(
这是我所说的构造函数(您可以在堆栈跟踪中看到它调用 getDeclaredConstructors)
@Inject
public CustomerController(
HashCreator hashCreator,
TokenGenerator tokenGenerator,
DataClientProxy clientProxy
) {
this.hashCreator = hashCreator;
this.tokenGenerator = tokenGenerator;
this.clientProxy = clientProxy;
}
最后这是堆栈跟踪
loadClass:521,ClassLoader (java.lang)
getDeclaredConstructors0:-1,Class (java.lang)
privateGetDeclaredConstructors:3137,Class (java.lang)
getDeclaredConstructors:2357,Class (java.lang)
forConstructorOf:245,InjectionPoint (com.google.inject.spi)
create:115,ConstructorBindingImpl (com.google.inject.internal)
createUninitializedBinding:706,InjectorImpl (com.google.inject.internal)
createJustInTimeBinding:930,InjectorImpl (com.google.inject.internal)
createJustInTimeBindingRecursive:852,InjectorImpl (com.google.inject.internal)
getJustInTimeBinding:291,InjectorImpl (com.google.inject.internal)
getBindingOrThrow:222,InjectorImpl (com.google.inject.internal)
getProviderOrThrow:1040,InjectorImpl (com.google.inject.internal)
getProvider:1071,InjectorImpl (com.google.inject.internal)
getProvider:1034,InjectorImpl (com.google.inject.internal)
getInstance:1086,InjectorImpl (com.google.inject.internal)
createController:29,DevLoader (org.webpieces.devrouter.impl)
为什么前两个参数是如何从 CompilingClassLoader 加载的,而第三个构造函数是如何从普通的 ClassLoader 加载的?我以为任何子类都应该通过与父类相同的类加载器加载?
(我正在试图修复这个问题,因为由于某种原因,CompilingClassLoader 没有加载该类,导致存在两个由不同类加载器加载的 DataApi.class 对象,这让我很困惑)。
嗯,当我更深入挖掘时,我发现可以调用 clazz.getMethods(),但是当我调用 clazz.getDeclaredConstructors() 时,会出现 ClassCircularityError。真正有趣的是,CustomerController 和 DataClientProxy 都没有继承任何类,所以这真的很奇怪。
Dean
英文:
createController on line 29 in the below stack trace has clazz.getClasslo
protected Object createController(Injector injector, String controllerClassFullName) {
Class<?> clazz = classLoader.clazzForName(controllerClassFullName);
return injector.getInstance(clazz); //line 29!!!!
}
loadClass online 521 is loading a class of the constructor of the above 'clazz' variable BUT is not loading from CompilingClassLoader. It somehow is skipping it. There are THREE parameters to the constructor all loading from CompilingClassLoader except the last one
Here is the constructor I am talking about(you can see it calling getDeclaredConstructors in the stack trace)
@Inject
public CustomerController(
HashCreator hashCreator,
TokenGenerator tokenGenerator,
DataClientProxy clientProxy
) {
this.hashCreator = hashCreator;
this.tokenGenerator = tokenGenerator;
this.clientProxy = clientProxy;
}
Finally here is the stack trace
loadClass:521, ClassLoader (java.lang)
getDeclaredConstructors0:-1, Class (java.lang)
privateGetDeclaredConstructors:3137, Class (java.lang)
getDeclaredConstructors:2357, Class (java.lang)
forConstructorOf:245, InjectionPoint (com.google.inject.spi)
create:115, ConstructorBindingImpl (com.google.inject.internal)
createUninitializedBinding:706, InjectorImpl (com.google.inject.internal)
createJustInTimeBinding:930, InjectorImpl (com.google.inject.internal)
createJustInTimeBindingRecursive:852, InjectorImpl (com.google.inject.internal)
getJustInTimeBinding:291, InjectorImpl (com.google.inject.internal)
getBindingOrThrow:222, InjectorImpl (com.google.inject.internal)
getProviderOrThrow:1040, InjectorImpl (com.google.inject.internal)
getProvider:1071, InjectorImpl (com.google.inject.internal)
getProvider:1034, InjectorImpl (com.google.inject.internal)
getInstance:1086, InjectorImpl (com.google.inject.internal)
createController:29, DevLoader (org.webpieces.devrouter.impl)
How in the world are the first two parameters loaded from CompilingClassLoader and the 3rd constructor is loaded from a normal ClassLoader. I thought any children classes should go through the same classloader as the parent to load?
(I am trying to fix this as for some reason, the CompilingClassLoader is missing loading that class causing a very fun like existence of TWO DataApi.class objects loaded by different classloaders).
Hmmm, As I dig more, I found out I can call clazz.getMethods() BUT when I call clazz.getDeclaredConstructors(), then I get a ClassCircularityError. The real funny thing is CustomerController nor DataClientProxy extend anyone so it's really weird.
Dean
答案1
得分: 0
Nastiness. 所以,这个文件有错误的包名。尽管 Eclipse 不允许这样做,而 Intellij 会将其标记为红色,但是 Gradle 和 Java 却可以正常编译,但是当我们寻找源代码时,我们找不到源代码,因此我们无法通过 CompilingClassLoader 加载它,从而导致了一个非常令人困惑的问题。我甚至无法抛出异常来告诉开发人员包名错误,因为我只接收类名,并且不知道包名是否错误,因为所有的类都会经过这个类加载器。糟糕。
英文:
Nastiness. So, the file had the wrong package name. While eclipse doesn't allow this and intellij flags it as red, gradle and java let it compile just fine but when we look for source, we can't find the source so it ends up we can't load it via the CompilingClassLoader causing a very confusing issue. I can't even throw an exception to this effect telling the developer the package is wrong because I only receve classnames and have no idea if the package name is wrong or not since all classes go through this classloader. ick.
专注分享java语言的经验与见解,让所有开发者获益!
评论