Thread.currentThread().setContextClassLoader为什么不生效与java.lang.NoClassDefFoundError之Java类加载的Parent first Classloader
- JVM将程序的部分类型在父加载器中加载了(比如系统或者父加载器)
- JVM将程序的其他部分想要在子加载器中加载(比如容器或者用户自定义加载器)
- 主程序NoClassDefFoundErrorSimulator会被打包在MainProgram.jar
- 日志输出程序JavaEETrainingUtil也被打包在MainProgram.jar
- caller类CallerClassA被打包在caller.jar
- 被引用的类ReferencingClassA被打包在referencer.jar
- 创建一个子加载器(java.net.URLClassLoader)
- 将caller.jar和referencher.jar分配给上面创建的子加载器
- 将当前线程上下文加载器更改为上面的子加载器
- 尝试从当前线程上下文加载器加载和创建CallerClassA类的实例
- 日志输出用来帮助理解类加载器的变化和线程上下文加载器的状态
- #### NoClassDefFoundErrorSimulator.java
- package org.ph.javaee.training3;
- import java.net.URL;
- import java.net.URLClassLoader;
- import org.ph.javaee.training.util.JavaEETrainingUtil;
- /**
- * NoClassDefFoundErrorSimulator
- * @author Pierre-Hugues Charbonneau
- *
- */
- public class NoClassDefFoundErrorSimulator {
- /**
- * @param args
- */
- public static void main(String[] args) {
- System.out.println("java.lang.NoClassDefFoundError Simulator - Training 3");
- System.out.println("Author: Pierre-Hugues Charbonneau");
- System.out.println("http://javaeesupportpatterns.blogspot.com");
- // Local variables
- String currentThreadName = Thread.currentThread().getName();
- String callerFullClassName = "org.ph.javaee.training3.CallerClassA";
- // Print current ClassLoader context & Thread
- System.out.println("\nCurrent Thread name: '"+currentThreadName+"'");
- System.out.println("Initial ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());
- try {
- // Location of the application code for our child ClassLoader
- URL[] webAppLibURL = new URL[] {new URL("file:caller.jar"),new URL("file:referencer.jar")};
- // Child ClassLoader instance creation
- URLClassLoader childClassLoader = new URLClassLoader(webAppLibURL);
- /*** Application code execution... ***/
- // 1. Change the current Thread ClassLoader to the child ClassLoader
- Thread.currentThread().setContextClassLoader(childClassLoader);
- System.out.println(">> Thread '"+currentThreadName+"' Context ClassLoader now changed to '"+childClassLoader+"'");
- System.out.println("\nNew ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());
- // 2. Load the caller Class within the child ClassLoader...
- System.out.println(">> Loading '"+callerFullClassName+"' to child ClassLoader '"+childClassLoader+"'...");
- Class<?> callerClass = childClassLoader.loadClass(callerFullClassName);
- // 3. Create a new instance of CallerClassA
- Object callerClassInstance = callerClass.newInstance();
- } catch (Throwable any) {
- System.out.println("Throwable: "+any);
- any.printStackTrace();
- }
- System.out.println("\nSimulator completed!");
- }
- }
- #### CallerClassA.java
- package org.ph.javaee.training3;
- import org.ph.javaee.training3.ReferencingClassA;
- /**
- * CallerClassA
- * @author Pierre-Hugues Charbonneau
- *
- */
- public class CallerClassA {
- private final static Class<CallerClassA> CLAZZ = CallerClassA.class;
- static {
- System.out.println("Class loading of "+CLAZZ+" from ClassLoader '"+CLAZZ.getClassLoader()+"' in progress...");
- }
- public CallerClassA() {
- System.out.println("Creating a new instance of "+CallerClassA.class.getName()+"...");
- doSomething();
- }
- private void doSomething() {
- // Create a new instance of ReferencingClassA
- ReferencingClassA referencingClass = new ReferencingClassA();
- }
- }
- #### ReferencingClassA.java
- package org.ph.javaee.training3;
- /**
- * ReferencingClassA
- * @author Pierre-Hugues Charbonneau
- *
- */
- public class ReferencingClassA {
- private final static Class<ReferencingClassA> CLAZZ = ReferencingClassA.class;
- static {
- System.out.println("Class loading of "+CLAZZ+" from ClassLoader '"+CLAZZ.getClassLoader()+"' in progress...");
- }
- public ReferencingClassA() {
- System.out.println("Creating a new instance of "+ReferencingClassA.class.getName()+"...");
- }
- public void doSomething() {
- //nothing to do...
- }
- }
- 主程序和工具包被部署在父加载器 (SYSTEM classpath)
- CallerClassA 和ReferencingClassA被部署在子加载器中
- ## Baseline (normal execution)
- <JDK_HOME>\bin>java -classpath MainProgram.jar org.ph.javaee.training3.NoClassDefFoundErrorSimulator
- java.lang.NoClassDefFoundError Simulator - Training 3
- Author: Pierre-Hugues Charbonneau
- http://javaeesupportpatterns.blogspot.com
- Current Thread name: 'main'
- Initial ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@17c1e333
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current Thread 'main' Context ClassLoader**
- -----------------------------------------------------------------
- >> Thread 'main' Context ClassLoader now changed to 'java.net.URLClassLoader@6a4d37e5'
- New ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@17c1e333
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@214c4ac9
- --- delegation ---
- java.net.URLClassLoader@6a4d37e5 **Current Thread 'main' Context ClassLoader**
- -----------------------------------------------------------------
- >> Loading 'org.ph.javaee.training3.CallerClassA' to child ClassLoader 'java.net.URLClassLoader@6a4d37e5'...
- Class loading of class org.ph.javaee.training3.CallerClassA from ClassLoader 'java.net.URLClassLoader@6a4d37e5' in progress...
- Creating a new instance of org.ph.javaee.training3.CallerClassA...
- Class loading of class org.ph.javaee.training3.ReferencingClassA from ClassLoader 'java.net.URLClassLoader@6a4d37e5' in progress...
- Creating a new instance of org.ph.javaee.training3.ReferencingClassA...
- Simulator completed!
- 主程序和工具类都被部署在父加载器(SYSTEM classpath)
- CallerClassA和ReferencingClassA被部署在子加载器
- CallerClassA (caller.jar)也被部署在父加载器
- ## Problem reproduction run (static variable initializer failure)
- <JDK_HOME>\bin>java -classpath MainProgram.jar;caller.jar org.ph.javaee.training3.NoClassDefFoundErrorSimulator
- java.lang.NoClassDefFoundError Simulator - Training 3
- Author: Pierre-Hugues Charbonneau
- http://javaeesupportpatterns.blogspot.com
- Current Thread name: 'main'
- Initial ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@17c1e333
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current Thread 'main' Context ClassLoader**
- -----------------------------------------------------------------
- >> Thread 'main' Context ClassLoader now changed to 'java.net.URLClassLoader@6a4d37e5'
- New ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@17c1e333
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@214c4ac9
- --- delegation ---
- java.net.URLClassLoader@6a4d37e5 **Current Thread 'main' Context ClassLoader**
- -----------------------------------------------------------------
- >> Loading 'org.ph.javaee.training3.CallerClassA' to child ClassLoader 'java.net.URLClassLoader@6a4d37e5'...
- Class loading of class org.ph.javaee.training3.CallerClassA from ClassLoader 'sun.misc.Launcher$AppClassLoader@214c4ac9' in progress...// Caller is loaded from the parent class loader, why???
- Creating a new instance of org.ph.javaee.training3.CallerClassA...
- Throwable: java.lang.NoClassDefFoundError: org/ph/javaee/training3/ReferencingClassA
- java.lang.NoClassDefFoundError: org/ph/javaee/training3/ReferencingClassA
- at org.ph.javaee.training3.CallerClassA.doSomething(CallerClassA.java:27)
- at org.ph.javaee.training3.CallerClassA.<init>(CallerClassA.java:21)
- at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
- at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
- at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
- at java.lang.reflect.Constructor.newInstance(Unknown Source)
- at java.lang.Class.newInstance0(Unknown Source)
- at java.lang.Class.newInstance(Unknown Source)
- at org.ph.javaee.training3.NoClassDefFoundErrorSimulator.main(NoClassDefFoundErrorSimulator.java:51)
- Caused by: java.lang.ClassNotFoundException: org.ph.javaee.training3.ReferencingClassA
- at java.net.URLClassLoader$1.run(Unknown Source)
- at java.net.URLClassLoader$1.run(Unknown Source)
- at java.security.AccessController.doPrivileged(Native Method)
- at java.net.URLClassLoader.findClass(Unknown Source)
- at java.lang.ClassLoader.loadClass(Unknown Source)
- at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
- at java.lang.ClassLoader.loadClass(Unknown Source)
- ... 9 more
- Simulator completed!
- 主程序和工具类都正常的从父加载器加载成功 (sun.misc.Launcher$AppClassLoader)
- 线程上下文加载器被更改为包含caller和reference的子加载器。
- 但是我们会看到CallerClassA 会被父加载器加载 (sun.misc.Launcher$AppClassLoader) ,并没有被子加载器加载
- 由于ReferencingClassA 没有被部署在父加载器, 所以他不能在当前加载器中加载,又由于父加载器对子加载器的无知,所以也不可能被子加载器加载。然后就报错NoClassDefFoundError。

- 仔细检视异常java.lang.NoClassDefFoundError并确定到底是哪个类导致问题
- 检视受影响的程序的打包方式,看看是否能找到是相应的类存在重复或者错误的部署方式。(SYSTEM class path, EAR file, Java EE container itself etc.).
- 如果找到了,那就需要将响应的类库从受影响的类加载器中移除。(有时会很复杂)
- 启用jvm的属性verbose,比如–verbose:class很有帮助,会帮助你定位类是从哪个加载器中加载的。
翻译自:https://javaeesupportpatterns.blogspot.com/2012/08/javalangnoclassdeffounderror-parent.html
Thread.currentThread().setContextClassLoader为什么不生效与java.lang.NoClassDefFoundError之Java类加载的Parent first Classloader的更多相关文章
- tomcat启动报错 关键字:java.lang.NoClassDefFoundError和 java.lang.ClassNotFoundExceeption
启动tomcat时报错情况如下图所示:实际上就是依赖的bean出错,百度上很多方法都说是tomcat没有部署正确,项目-->右键----->proterties----->Targe ...
- CentOS6.5 静默安装Oracle 11g过程中提示:Exception in thread “main” java.lang.NoClassDefFoundError
原来是系统中设置了DISPLAY环境变量,执行: [oracle@qa26 database]$ ./runInstaller -silent -responseFile /usr/local/or ...
- 【转】怎么解决java.lang.NoClassDefFoundError错误 ,以及类的加载机制
转自http://blog.csdn.net/jamesjxin/article/details/46606307 前言 在日常Java开发中,我们经常碰到java.lang.NoClassDefFo ...
- 【eclipse】 怎么解决java.lang.NoClassDefFoundError错误
前言 在日常Java开 发中,我们经常碰到java.lang.NoClassDefFoundError这样的错误,需要花费很多时间去找错误的原因,具体是哪个类不见了?类 明明还在,为什么找不到?而且我 ...
- 在centOS上安装oracle出现java.lang.NoClassDefFoundError问题及解决方法
问题一:CentOS6.5 静默安装Oracle 11G过程中提示:Exception in thread "main" java.lang.NoClassDefFoundErro ...
- Caused by: java.lang.NoClassDefFoundError:
tomcat启动不了 报错信息头如下: Caused by: java.lang.NoClassDefFoundError: at java.lang.Class.getDeclaredMethods ...
- java.lang.NoClassDefFoundError 错误
练习jfianl,,,配置数据库插件的时候遇到: java.lang.NoClassDefFoundError: com/mchange/v2/c3p0/ComboPooledDataSource 解 ...
- 关于怎么解决java.lang.NoClassDefFoundError错误
五一在部署新的统一登录时,遇到这样一个问题: 很容易把java.lang.NoClassDefFoundError和java.lang.ClassNotfoundException这两个错误搞混,事实 ...
- ClassLoader,Thread.currentThread().setContextClassLoader,tomcat的ClassLoader
实际上,在Java应用中所有程序都运行在线程里,如果在程序中没有手工设置过ClassLoader,对于一般的java类如下两种方法获得的ClassLoader通常都是同一个 this.getClass ...
随机推荐
- 一款对Postman支持较好的接口文档生成工具
最近要编写接口文档给测试和前端看,通过网上查阅资料,也认识了很多款接口文档生成工具,比如易文档.ApiPost.ShowDoc.YApi.EoLinker.DOClever.apizza等,通过对这几 ...
- Java自学-集合框架 HashSet
Java集合框架 HashSet 示例 1 : 元素不能重复 Set中的元素,不能重复 package collection; import java.util.HashSet; public cla ...
- SpringBoot+Swagger整合
0.引言及注意事项 Swagger是一个接口文档工具,依照Swagger可以0配置开发接口.不过要注意,Swagger是基于SpringBoot1.47版本开发的,而SpringBoot现在基本都是是 ...
- 腾讯WeTest亮相—腾讯全球数字生态大会现场
2019年5月21-23日腾讯全球数字生态大会在云南昆明滇池国际会展中心顺利召开. 此次大会上万人到场参与,大会由主峰会.分论坛.数字生态专题展会以及腾讯数字生态人物颁奖盛典四大板块构成.作为腾讯战略 ...
- strace命令 系统调用
简介 strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核 ...
- odoo12 如何设置超级用户
在odoo12的版本中,和之前的版本有点不一样的地方 在odoo12版本之前,每个实例都是使用户名为Administrator的默认用户来创建的. 在数据库中user_id是1. 在代码中,你会发现 ...
- C# 测试网络速度例子
using System.Net.NetworkInformation; namespace PingExample { public partial class Form1 : Form { pub ...
- 打开前端工程 Node Sass does not yet support your current environment: Windows 64-bit
卸载当前sass版本,重新安装sass 打开cmd进入工程文件夹: 删除 npm uninstall --save node-sass 安装 npm install --save node-sass ...
- Confluence 6.9.0 安装
平台环境:centos 7.6 数据库版本:mysql-5.7.26,提前安装好,安装步骤略. 软件版本:Confluence6.9.0 所需软件:提前下载到本地电脑 atlassian-conflu ...
- Docker镜像服务(二)
一.Docker镜像介绍 镜像是Docker的三大核心概念之一. Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认的镜像仓库下载(默认使用Docker Hu ...