一次不引用包跑外部依赖的实践
c7aaa6007d37d29d3b94d9a420f710abebb1fdec
1 spi


解决方式:把invoke放到新线程
2 log4j


2.1
log4j让平行加载器tomcatwebappclassloader加载行不行,
如果log.info(a class only in sub classloader) ,那么平行加载器企图调用tostring时会认不出
平行加载器可以调用某个我不认识的类的对象的方法
d20240703.ParquetCreator d20240703.MyException d20240703.ParquetInter bingo interface parquet impl d20240703.RandomClass bingo class random in sub hhhhxxx hhhstarthhh-----java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at d20240703.MyParquetCallable.call(MyParquetCallable.java:33) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at lc2024.d20240703.TomcatBoot.main(TomcatBoot.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused by: d20240703.MyException at d20240703.ParquetCreator.start(ParquetCreator.java:13) ... 15 more d20240703.CNotExistInSub 构造CNotExistInSub 从与ParquetClassLoader平行的MyWebAppLoader中也能调用本方法 即使MyWebAppLoader压根没有加载过本类 再往Exception上扩展,本module特有的Exception,那边也能识别
2.1.5
参考
https://www.cnblogs.com/gifisan/p/6879465.html 多个classloader加载log4j时需要设置当前Thread的classloader为你自己的classloader
log4j:ERROR A "org.apache.log4j.DailyRollingFileAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
多个classloader加载log4j时需要设置当前Thread的classloader为你自己的classloader
Thread.currentThread().setContextClassLoader(classLoader); //for log4j
摘自:org.apache.log4j.helpers.Loader
复制代码
/**
* If running under JDK 1.2 load the specified class using the
* <code>Thread</code> <code>contextClassLoader</code> if that
* fails try Class.forname. Under JDK 1.1 only Class.forName is
* used.
*
*/
static public Class loadClass (String clazz) throws ClassNotFoundException {
// Just call Class.forName(clazz) if we are running under JDK 1.1
// or if we are instructed to ignore the TCL.
if(java1 || ignoreTCL) {
return Class.forName(clazz);
} else {
try {
return getTCL().loadClass(clazz);
} catch(Throwable e) {
// we reached here because tcl was null or because of a
// security exception, or because clazz could not be loaded...
// In any case we now try one more time
return Class.forName(clazz);
}
}
复制代码
复制代码
log4j:ERROR A "org.apache.log4j.DailyRollingFileAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
log4j:ERROR [com.generallycloud.baseio.container.URLDynamicClassLoader@55740540] whereas object of type
log4j:ERROR "org.apache.log4j.DailyRollingFileAppender" was loaded by [sun.misc.Launcher$AppClassLoader@18b4aac2].
log4j:ERROR Could not instantiate appender named "main".
log4j:ERROR A "org.apache.log4j.ConsoleAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
log4j:ERROR [com.generallycloud.baseio.container.URLDynamicClassLoader@55740540] whereas object of type
log4j:ERROR "org.apache.log4j.ConsoleAppender" was loaded by [sun.misc.Launcher$AppClassLoader@18b4aac2].
log4j:ERROR Could not instantiate appender named "console".
log4j:WARN No appenders could be found for logger (com.generallycloud.baseio.component.ssl.SSLUtil).
log4j:WARN Please initialize the log4j system properly.
复制代码
原文:http://www.cnblogs.com/gifisan/p/6879465.html
https://www.cnblogs.com/gifisan/p/6879465.html
2.2
因为invoke虽然在新线程,但是invoke所在那个类的load是在原线程做的,而log4j在load时已被static引用并加载
before
new classloader
c = loadclass(the entrance) ----- now log4j start load because of the static logger in the entrance
then log4j get the classloader of current thread
new thread (c.new instance.run)
after
new classloader
new thread (every thing)

日志继续留在tomcat catelina.out标准输出
2.3 如果抛出一个平行加载器特有的exception
在2.1中已经证明在类加载器CA中类A的方法中调用平行类加载CB中类B的方法是可以的,那么从系统上,这个try catch等同于一般情况
1)能否抓住
2)能否打印堆栈
both idea and assemply can trace it, even though override it's tostring, which means when calling e.toString it must point to the method in subclassloader
一种合理的解释为,父加载器的try catch拿到的是个Exception的指针,并不需要知道类型
但是线上确实出现了没有causedby的但打印了原异常的情况,说明异常传递了但传递出错了;最终只能依托于子包自己里面的日志体系,放弃在父调用地去打印堆栈
20240801
浙公网安备 33010602011771号