由初始化线程池引发的NoClassDefFoundError 异常分析
今天说的异常是一个很不常见的异常,至少我不经常见到这个异常。
首先先看下NoClassDefFoundError官方定义 :
Java Virtual Machine is not able to find a particular class at runtime which was available at compile time. If a class was present during compile time but not available in java classpath during runtime.
Java 虚拟机无法在运行时找到一个在编译时可用的特定类。如果在编译时存在类, 但在运行时 java 类路径中不可用。
最近做的一个项目,由同事到客户方部署及应用,但是期间发生一个诡异的问题:同一套代码打出的jar包在一个公司运行时会有一个NoClassDefFoundError异常抛出。起初看到这个异常,我们都认为是打得包或者依赖有问题。于是便重新打包部署,结果还是同样的问题。异常信息如下:
很诡异的问题,顺着报的错误去继续查找原因,最后将问题定位到一个线程池工具类中,部分代码如下:
其中 DEFAULT_MAX_CONCURRENT 定义如下:
private static final int DEFAULT_MAX_CONCURRENT = Runtime.getRuntime().availableProcessors() * 2;
这个线程池工具类在本地以及测试环境和线上环境一直都运行的没有问题,因为报错的异常信息指向了这个类。
考虑到在多个客户部署的都是同一套代码,只有硬件配置可能不同,而我们线程池初始化时的核心线程数依赖于硬件CPU核数,所以便猜测初始化线程池出了问题,核心线程数可能比最大线程数还大。
于是便开始追踪源码,一探究竟。
线程池初始化源码:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
继续往下看其初始化过程:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < ||
maximumPoolSize <= ||
maximumPoolSize < corePoolSize ||
keepAliveTime < )
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
上面代码可能看出,如果corePoolSize>maxPoolSize 则会抛出:IllegalArgumentException 异常,但是这和我们问题压根不一样啊?线索到这里就断了,但是至少发现了代码的一处Bug。
于是又开始沉思这个NoClassDefFoundError 异常究竟是怎么来的了,打开Oracle 文档便开始全局搜索这个,果不其然,有了新的发现:
(文档地址:https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2)
这里意思是初始化过程时,如果这个类是用c去实现的,且初始化抛出异常时,都会对外抛出NoClassDefFoundError 异常,到了这里就很明朗了,果然是初始化线程池搞错了。
于是赶紧查看客户机器CPU核数来验证自己的猜想,果不其然,CPU为8核处理器。赶紧改了代码重新打包部署,一切到这里就结束了。
不过通过这次异常也学到了很多:
1,能不用硬编码的应该坚决杜绝,少埋这种坑。
2,多查文档,多查官方文档。
由于博主能力有限,所以如果您有更多的见解还请留言告知,不胜感激。
由初始化线程池引发的NoClassDefFoundError 异常分析的更多相关文章
- 启用Executor初始化线程池
前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...
- Tomcat启动时加载数据到缓存---web.xml中listener加载顺序(例如顺序:1、初始化spring容器,2、初始化线程池,3、加载业务代码,将数据库中数据加载到内存中)
最近公司要做功能迁移,原来的后台使用的Netty,现在要迁移到在uap上,也就是说所有后台的代码不能通过netty写的加载顺序加载了. 问题就来了,怎样让迁移到tomcat的代码按照原来的加载顺序进行 ...
- SpringCloud 微服务中 @Async 注解自定义线程池 引发的aop 问题
背景 在 使用springCloud 的@Async注解来做异步操作时,想自定义其线程池. 引发问题 自定义完线程池后,发现代码里并没有使用自定义线程池里的线程,于是新建一个demo工程,一样的配置代 ...
- Java ThreadPoolExecutor线程池原理及源码分析
一.源码分析(基于JDK1.6) ThreadExecutorPool是使用最多的线程池组件,了解它的原始资料最好是从从设计者(Doug Lea)的口中知道它的来龙去脉.在Jdk1.6中,Thread ...
- Java线程池ThreadPoolExector的源码分析
前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等 ...
- Java线程池ThreadPoolExecutor类源码分析
前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...
- JUC(4)---java线程池原理及源码分析
线程池,既然是个池子里面肯定就装很多线程. 如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁 线程,如此一来会大大降低系统的效率.可能出现服务器在为每个请求创建新线程和销毁 ...
- 详解Java线程池的ctl(线程池控制状态)【源码分析】
0.综述 ctl 是线程池源码中常常用到的一个变量. 它的主要作用是记录线程池的生命周期状态和当前工作的线程数. 作者通过巧妙的设计,将一个整型变量按二进制位分成两部分,分别表示两个信息. 1.声明与 ...
- JAVA线程池原理与源码分析
1.线程池常用接口介绍 1.1.Executor public interface Executor { void execute(Runnable command); } 执行提交的Runnable ...
随机推荐
- MySQL排序:SELECT ORDER BY
SELECT 和ORDER BY结合进行排序: products表例如以下: a 按产品名称列进行排序: b 按多个列进行排序,默认排序顺序为升序: c 指定排序方向,即指定为降序: d 对多个列进行 ...
- 算法笔记_202:第三届蓝桥杯软件类决赛真题(Java高职)
目录 1 填算式 2 提取子串 3 机器人行走 4 地址格式转换 5 排日程 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 填算式 [结果填空] (满分11分) 看这个算式: ☆☆☆ + ☆☆ ...
- 江南白衣整理和开发的java常用工具类
江南白衣的公众号的介绍文章:http://mp.weixin.qq.com/s/6JUo1vmUa-7SuDH6yIxKeQ github的地址:https://github.com/springsi ...
- java的配置方式简介
1,java的配置方式简介java的配置方式是为了代替使用xml配置方式,主要使用两个注解:@Configuration//通过该注解来表明该类是一个spring的配置,相当于一个xml文件@Comp ...
- 转:TCP/IP协议栈的基本工作原理
转载自:http://jasonccie.blog.51cto.com/2143955/422966 TCP/IP是互联网的核心协议,也是大多数网络应用的核心协议.就前面一段时间面试中问到的TCP/I ...
- java服务端微信小程序支付
发布时间:2018-10-05 技术:springboot+maven 概述 java微信小程序demo支付只需配置支付一下参数即可运行 详细 代码下载:http://www.demodash ...
- 利用jquery修改href的部分字符
试了好久 就一句代码即可. $(document).ready(function(){ $('a').each(function(){ this.href = this.href.replace('y ...
- java实现读取ftp服务器上的csv文件
定义ftp操作接口 import java.io.InputStream; import java.util.List; import org.apache.commons.net.ftp.FTPCl ...
- QQ 互联认证 回调地址提示说要http :// 但是事实不用
真奇怪 腾讯最近人手不够吧 这样的错误也会犯错....
- 强力密码暴力破解工具:hydra
语法: hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e nsr] [-o FILE] [-t TASKS] [-M FIL ...