问题标签 [contextclassloader]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 无法使用主线程的上下文类加载器将 Web 应用程序添加到 @SpringBootApplication 的内置 Tomcat
我正在尝试加载war
我的独立版附带的 Web 应用程序jar
。在我@SpringBootApplication
启动时,我提取war
文件并将其复制到文件系统。之后,我打了一个简单的tomcat.addWebapp()
电话,我希望它可以工作。但是看看:
问题是我在退货后马上得到了很多。您可以在此处查看完整输出,但归结为:FileNotFoundException
servletContainerFactory()
最后一个例外ClassNotFoundException
肯定与上述错误有关:
似乎所有依赖项都丢失了。问题是我必须做什么才能解决这个问题。正如建议的那样,我也将tomcat-embed-core
依赖项放到了 Spring 应用程序的 pom.xml 中,但这不起作用。
任何帮助表示赞赏!
java - 在 ClassLoader 上调用 `defineClass` 会导致“找不到匹配的方法”
我使用 ASM 生成了一个类,现在我尝试使用 ContextClassLoader 加载这个类:
controllerclass 是包含该类的字节数组。我得到的例外是:
我尝试添加类型提示,但没有效果。我如何告诉 Clojure 究竟使用哪种方法?这些类型肯定与 Java 8 的 javadoc 中显示的类型相匹配。
java - Tomcat升级后并行流不设置Thread.contextClassLoader
在 tomcat 从 8.5.6 升级到 8.5.28 并行流后停止为线程提供 contextClassLoader:
因为它Warmer::run
无法在其中加载类。
你知道 Tomcat 为新线程的 contextClassLoaders 提供了什么吗?
ParallelStream 在最新的 Tomcat 中使用 ForkJoinPool。
java - Java ClassLoader getResources 不适用于 Launcher$AppClassLoader
此代码片段在被 websphere 服务器调用时工作正常(cl 的类型为 com.ibm.ws.classloader.CompoundClassLoader)。
但是,当我从 main 方法在独立类中运行相同的代码时(通过将 abc.xml 的文件夹路径添加到运行时配置), resnum 为空。cl 是 sun.misc.Launcher$AppClassLoader 类型。如果我从代码中删除“/”,它工作正常。有没有办法可以在 abc.xml 之前加载一个“/”(可能使用其他一些类加载器)?请帮忙。
java - 带有相关 ClassLoader 的 getSystemResource() 与 getResource()
问题一:
ClassLoader.getSystemResource("img.png");
完全一样,有ClassLoader.getSystemClassLoader().getResource("img.png");
什么区别(更喜欢哪一个?)。我期待答案“两者都不使用”(在应用程序服务器内),那么我们在 API 中有这些方法是为了什么?
问题二:
将我的 WAR/应用程序放在 Tomcat/其他 AppServer 中,我是否应该总是使用Thread.currentThread().getContextClassLoader().getResourceAsStream("img.png")
而不考虑其他更合适的用例(例如,objOfMyOwnClassCreatedAnywhereWithinMyApp.getClass().getClassLoader().getResource("sth")
?
总结一下我知道的:
对比
对比
我的理解是否正确:
1)在任何应用程序服务器(包括 Tomcat)中,我将只使用Thread.currentThread().getContextClassLoader().getResourceAsStream("NoSlash!_Img.png");
1.1)我永远不会使用其余的任何东西(在任何应用服务器上)
2)在桌面应用程序上,以上所有内容都是等效的
3) Tomcat 本身(包含 main() 的类 - Tomcat 的入口点)使用系统类加载器加载 - 始终可以(100%?)被识别为ClassLoader.getSystemClassLoader()
我System.setProperty("java.system.class.loader")
不清楚什么。此外,obj.getClass().getClassLoader().getSystemClassLoader()
也应返回与 相同ClassLoader.getSystemClassLoader()
,但它可能会返回null
(如果自定义类加载器的实现者决定他们最好不要公开系统类加载器)。除了 null 和真正的 System ClassLoaderobj.getClass().getClassLoader().getSystemClassLoader()
可能不会返回任何其他内容(因为返回一些其他类加载器会很愚蠢?)。
4) Tomcat / 另一个应用程序服务器中的任何 Web 应用程序 (= context = WAR) 都使用其单独的(自定义)类加载器(有时称为“应用程序类加载器”,这将其与“系统类加载器”混淆,有时也称为“应用程序类加载器”)。如果我在 A 类方法中,调用this.getClass().getClassLoader()
会为我提供(自定义)类加载器,它加载了我的 A 类(以及我的整个 WAR / 应用程序)。
那么我为什么要使用Thread.currentThread().getContextClassLoader().getResource("sth")
而不是this.getClass().getClassLoader().getResource("sth")
呢?我认为最好使用我的 WAR 自定义类加载器!
上下文类加载器在我的 WAR 的所有线程中是否始终相同(除非我自己启动线程并弄乱上下文类加载器)并且与加载我的 WAR(objOfMyOwnClassesCreatedAnywhereWithinMyApp.getClass().getClassLoader()
)的自定义类加载器相同?
PS这里的答案意味着我更喜欢使用上下文类加载器的一种情况。这意味着在许多其他情况下不使用上下文类加载器是可以的(当在我的线程上创建的对象没有提供给任何其他线程时,尤其是没有由我创建的其他线程时)。
每个类都将使用自己的类加载器来加载其他类。因此,如果 ClassA.class 引用 ClassB.class 那么 ClassB 需要位于 ClassA 的类加载器或其父级的类路径上。
线程上下文类加载器是当前线程的当前类加载器。可以从 ClassLoaderC 中的类创建对象,然后将其传递给 ClassLoaderD 拥有的线程。 在这种情况下,对象需要直接使用 Thread.currentThread().getContextClassLoader()如果它想加载它自己的类加载器上不可用的资源。
除了这里的 Stackoverflow 答案(@yonran)建议:
永远不要使用上下文类加载器!
java - 类加载器如何加载在方法中声明的扩展类的实例?(java.lang.NoClassDefFoundError)
我有一个具有实用功能的类,可以按需调用。
重现步骤 :
- TestMainWebApp(这个项目有TestMainImp的依赖)
- TestMainImpl (这个项目实现了TestMainInterface)
- 测试主接口
TestMainWebApp > TestMainServlet.java
TestMainImpl > Util.java & TLSErrorRedirectListener.java
TLSErrorRedirectionListener.java
TestMainInterface > ConfigurationListener.java
案子 :
- TestMainInterface.jar 将在 TestMainImpl.jar 的类路径中(仅限@compiletime)
- 在运行时(我不会有 TestMainInterface.jar)并且我不调用方法 "checkForTLSErrorRedirection()" 。我只调用 test() 方法。
但是当我自己创建实例时,我得到了 java.lang.NoClassDefFoundError: test/intf/ConfigurationListener 。
你能帮忙找出根本原因吗?java如何加载在方法中声明的类?
注意: 用于调试目的的JavaEETrainingUtil.java
java - CompilingClassLoader 很有趣,在这种情况下如何从不同的类加载器加载子类?
以下堆栈跟踪中第 29 行的 createController 具有 clazz.getClasslo
loadClass online 521 正在加载上述“clazz”变量的构造函数的类,但未从 CompilingClassLoader 加载。它以某种方式跳过它。构造函数有三个参数,所有参数都是从 CompilingClassLoader 加载的,除了最后一个:(
这是我正在谈论的构造函数(您可以在堆栈跟踪中看到它调用 getDeclaredConstructors)
最后是堆栈跟踪
世界上的前两个参数是如何从 CompilingClassLoader 加载的,而第三个构造函数是从普通的 ClassLoader 加载的。我认为任何子类都应该通过与父类相同的类加载器来加载?
(由于某种原因,我正在尝试解决此问题,CompilingClassLoader 缺少加载该类,导致非常有趣,例如存在由不同类加载器加载的两个 DataApi.class 对象)。
嗯,当我深入挖掘时,我发现我可以调用 clazz.getMethods() 但是当我调用 clazz.getDeclaredConstructors() 时,我得到一个 ClassCircularityError。真正有趣的是 CustomerController 或 DataClientProxy 扩展任何人,所以这真的很奇怪。
院长
java - Thread.currentThread().getContextClassLoader() 的行为与 Jetty 9.4.37.v20210219 不同
我在从 Jetty 版本加载 Web 应用程序中的资源文件时遇到问题9.4.37.v20210219
。
我正在Thread.currentThread().getContextClassLoader()
获取类加载器实例,然后尝试使用classLoader.getResourceAsStream("resourceFileName")
. 这行代码从 jetty version 返回 null 9.4.37.v20210219
。
通过在码头版本中记录类加载器实例进行比较研究时9.4.37.v20210219
,9.4.36.v20210114
我看到以下差异
在码头 9.4.37.v20210219,我得到
startJarLoader@1c4af82c
但是使用码头 9.4.36.v20210114,我得到
WebAppClassLoader{984235065}@3aaa3c39
startJarLoader 是否指示码头服务器类路径?从 webapp 加载资源文件的标准方法是什么?
附加信息,我的 Web 应用程序已部署在其中,JETTY_BASE/webapps
并且我有要在其中加载的资源文件。这个 webapp 有一个依赖 jar,它部署在JETTY_BASE/lib/ext
. Thread.currentThread().getContextClassLoader()
在 webapp 内部的方法中使用,该方法从其依赖项 jar 中调用。换句话说,被调用的线程属于 webapp 的依赖 jar,它位于服务器类路径/父类加载器中。这就是我猜的原因,但我想知道为什么从码头9.4.37.v20210219
和更高版本中可以看到这种差异。
顺便说一句,做MyClass.class.getClassLoader()
退货WebAppClassLoader{984235065}@3aaa3c39
,我可以使用相同的方式将资源作为流获取,classLoader.getResourceAsStream("resourceFileName")
但我想知道为什么行为与 jetty version 有所不同9.4.37.v20210219
。
感谢任何帮助!提前致谢!
spring - Spring Devtools 的 RestartClassLoader 是否违反了类加载原则的唯一性?
我使用支持实例化MyBatis的库。org.apache.ibatis.type.TypeHandler
它适用于没有devtools
.
但是devtools
,它不起作用。
我发现当前线程中的上下文类加载器更改为org.springframework.boot.devtools.restart.classloader.RestartClassLoader
.
类加载遵循三个简单的原则:
- 委托——委托原则在类尚未加载时指导我们。在这种情况下,子类加载器要求其父类加载类,直到检查引导类加载器(它确保对象层次结构 java.lang.Object 顶部的父类相同)
- 可见性——可见性原则确保子类加载器可以看到其父类加载的所有类。但是,反之则不然,父级看不到其子级加载的类(否则它就像一个平面类加载器,加载所有内容而没有任何隔离级别)
- 唯一性——唯一性原则确保一个类在类加载器层次结构的生命周期中只加载一次(由于子类对父类具有可见性,它永远不会尝试加载父类已经加载的类,但两个兄弟姐妹可能最终会在各自的类加载器中加载相同的类)
我认为RestartClassLoader
违反了第三个原则,对吗?