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 ...
随机推荐
- Qt背景不显示问题
背景不显示的只有主窗口会发生,原因是主窗口使用的QWidget类 解决办法 重构paintEvent事件,添加即可 void LoginWidget::paintEvent(QPaintEvent * ...
- Redis 使用过程中遇到的具体问题
1.缓存雪崩和缓存穿透问题 1.1缓存雪崩 简介:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉. 解决办法: 事前:尽量保证整个 redis 集 ...
- 002-Zabbix 前端配置
Zabbix 前端配置 [基于此文章的环境]点我快速打开文章 [官方地址]点我快速打开文章 第 1 步 在浏览器中,打开 Zabbix URL:http:// <server_ip_or_nam ...
- 程序员代码面试指南 IT名企算法与数据结构题目最优解
原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...
- luoguP4393Sequence
https://www.luogu.org/problem/P4393 题意 给你n个点的一个数列,每次可以合并两个相邻的数为他们的最大值,且代价为这两个数的最大值,求将整个序列合并为1个数的最小代价 ...
- 解决chrome连接自建https服务器报“您的连接不是私密连接”问题
前一段时间,Chrome 突然显示出了“您的连接不是私密连接”,这下可难受了,大部分的网站打开都有问题. 找了各种方法,各种设置都是不行. 一.暴力.费力的方法直接卸载 Chrome ,删除一切数据以 ...
- JVM 启动参数,共分为3类
JVM 启动参数,共分为3类: 类别 说明 标准参数(-) 所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 非标准参数(-X) 这些参数不是虚拟机规范规定的.因此,不是所有VM的实现(如:H ...
- day39_8_23mysql的其他内容(视图等)
一.视图 MySQL中有一种比较方便的表,就是视图(view). 什么是视图? 视图就是通过查询获得一张虚拟表,然后将其保存,下次可以直接使用这个视图. 使用视图就可以不需要重复查询/连接表,在代码层 ...
- OSI网络七层模型、TCP/IP 模型(四)
OSI 是 Open System Interconnection 的缩写,译为“开放式系统互联”. OSI 模型把网络通信的工作分为 7 层,从下到上分别是物理层.数据链路层.网络层.传输层.会话层 ...
- java 启动jar 指定端口
java 启动jar 指定端口 java -jar xxx.jar --server.port=80