ClassNotFoundException:是否会减慢您的JVM?

大多数Java开发人员都熟悉臭名昭著且非常常见的java.lang.ClassNotFoundException 。 虽然通常已经很好地了解了此问题的根源(类路径中缺少类/库,类加载器委派问题等),但对整体JVM和性能的影响通常是未知的。 这种情况可能会严重影响您的应用程序响应时间和可伸缩性。

部署了多个应用程序的大型Java EE企业系统最容易遭受此类问题的影响,因为在运行时会激活大量不同的应用程序类加载器。 除非确定了明确的业务影响并实施了紧密的日志监视,否则这将面临面临“未检测到” ClassNotFoundException的风险,从而导致:持续的性能影响以及可能的JVM类加载IO和线程锁争用。

下面的文章和示例程序将说明从客户生产系统中发现的ClassNotFoundException的任何出现都应予以认真对待并Swift解决。

Java类加载:缺少链接以获得最佳性能

对性能问题的正确理解始于对Java类加载模型的正确了解。 ClassNotFoundException本质上意味着JVM无法定位和/或加载特定的Java类,例如:

  • Class.forName()方法
  • ClassLoader.findSystemClass()方法
  • ClassLoader.loadClass()方法

尽管应用程序类的类加载在JVM生命周期中(或通过动态重新部署功能)应该只发生一次,但某些应用程序也依赖于动态类加载操作。

无论如何,重复的有效和“失败”类加载操作可能非常麻烦,特别是当默认JDK java.lang.ClassLoader本身尝试加载过程时。 实际上,由于向后兼容性,默认的JDK 1.7+行为将仅允许一次加载一个类,除非将类加载器标记为“具有并行功能”。 请记住,即使同步仅在类级别完成,针对相同类名的重复类加载失败仍将触发线程锁争用,具体取决于您正在处理的Java线程并发级别。 回到JDK 1.6时,情况最糟糕,在类加载器实例级别系统地完成了同步。

ClassNotFoundException_img1

ClassNotFoundException_img2

因此,诸如JBoss WildFly 8之类的Java EE容器正在使用它们自己的内部并发类加载器来加载应用程序类。 这些类加载器实现了更细粒度的锁定,因此允许从类加载器的同一实例中同时加载不同的类。 这也与最新的JDK 1.7+改进保持一致,后者引入了对多线程自定义类加载器的支持,这也有助于防止某些类加载器出现死锁情况。

话虽这么说,系统级类(例如java。*和Java EE容器模块)的类加载仍然依靠默认的JDK ClassLoader。 这意味着相同类名(例如ClassNotFoundException)的重复类加载失败仍会触发严重的线程锁争用。 这正是我们将在本文的其余部分中重复和演示的内容。

线程锁争用–问题复制

为了重新创建和模拟此问题,我们根据以下规范创建了一个简单的应用程序:

  • 一个JAX-RS(REST)Web服务,对系统包级别中“定位”的虚拟类名称执行Class.forName():

字符串className =“ java.lang.WrongClassName”;

类。 forName (className);

  • JRE:HotSpot JDK 1.7 @ 64位
  • Java EE容器: JBoss WildFly 8
  • 负载测试工具: Apache JMeter
  • Java监控:JVisualVM
  • Java并发故障排除: JVM线程转储分析

该仿真实际上与20个线程同时执行JAX-RS Web服务。 每次调用都会生成ClassNotFoundException。 为了减少对IO的影响并仅关注类加载争用,完全禁用了日志记录。

现在,让我们看看从30到60秒的运行情况来看JVisualVM的结果。 我们可以清楚地看到很多BLOCKED线程正在等待获取对象监视器上的锁。

ClassNotFoundException_img3

对JVM线程转储的分析清楚地揭示了问题所在:线程锁争用。 从执行堆栈跟踪中我们可以看到JBoss将类的加载委托给JDK ClassLoader ...为什么? 这是因为检测到我们错误的Java类名称是系统类路径的一部分,例如java。*。 在这种情况下,JBoss将把加载委托给系统类加载器,从而触发该特定类名称的系统同步,并等待来自其他线程的服务员等待获取锁以加载相同的类名称。

许多线程正在等待获取LOCK 0x00000000ab84c0c8…

"default task-15" prio=6 tid=0x0000000014849800 nid=0x2050 waiting for monitor entry [0x000000001009d000]              java.lang.Thread.State: BLOCKED (on object monitor)                                                                  at java.lang.ClassLoader.loadClass(ClassLoader.java:403)                                                             - waiting to lock <0x00000000ab84c0c8> (a java.lang.Object)// Waiting to acquire a LOCK held by Thread “default task-20”                                                     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:356)    // JBoss now delegates to system ClassLoader..                                                          at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:371)                          at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119)                                 at java.lang.Class.forName0(Native Method)                                                                           at java.lang.Class.forName(Class.java:186)                                                                           at org.jboss.tools.examples.rest.MemberResourceRESTService.SystemCLFailure(MemberResourceRESTService.java:176)       at org.jboss.tools.examples.rest.MemberResourceRESTService$Proxy$_$$_WeldClientProxy.SystemCLFailure(Unknown Source) at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)                                                       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)                             at java.lang.reflect.Method.invoke(Method.java:601)    
……………………..

罪魁祸首线程–默认任务20

"default task-20" prio=6 tid=0x000000000e3a3000 nid=0x21d8 runnable [0x0000000010e7d000]                             java.lang.Thread.State: RUNNABLE                                                                                   at java.lang.Throwable.fillInStackTrace(Native Method)                                                             at java.lang.Throwable.fillInStackTrace(Throwable.java:782)                                                        - locked <0x00000000a09585c8> (a java.lang.ClassNotFoundException)                                                 at java.lang.Throwable.<init>(Throwable.java:287)                                                                  at java.lang.Exception.<init>(Exception.java:84)                                                                   at java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:75)                             
at java.lang.ClassNotFoundException.<init>(ClassNotFoundException.java:82) // ClassNotFoundException!                                      at java.net.URLClassLoader$1.run(URLClassLoader.java:366)                                                          at java.net.URLClassLoader$1.run(URLClassLoader.java:355)                                                          at java.security.AccessController.doPrivileged(Native Method)                                                      at java.net.URLClassLoader.findClass(URLClassLoader.java:354)                                                      at java.lang.ClassLoader.loadClass(ClassLoader.java:423)                                                           - locked <0x00000000ab84c0e0> (a java.lang.Object)                                                                  at java.lang.ClassLoader.loadClass(ClassLoader.java:410)                                                           
- locked <0x00000000ab84c0c8> (a java.lang.Object)   // java.lang.ClassLoader: LOCK acquired                                                             at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)                                                   at java.lang.ClassLoader.loadClass(ClassLoader.java:356)                                                           at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:371)                        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119)                               at java.lang.Class.forName0(Native Method)                                                                         at java.lang.Class.forName(Class.java:186)                                                                         at org.jboss.tools.examples.rest.MemberResourceRESTService.SystemCLFailure(MemberResourceRESTService.java:176)     at org.jboss.tools.examples.rest.MemberResourceRESTService$Proxy$_$$_WeldClientProxy.SystemCLFailure(Unknown Source)
…………………………………

现在,让我们用标记为“应用程序”包的一部分的Java类替换我们的类名称,然后在相同的负载条件下重新运行测试。

String className = "org.ph.WrongClassName";
Class.forName(className);

ClassNotFoundException_img4

如我们所见,我们不再处理阻塞的线程……为什么呢? 让我们看一下JVM线程转储,以更好地了解这种行为变化。

"default task-51" prio=6 tid=0x000000000dd33000 nid=0x200c runnable [0x000000001d76d000]                               java.lang.Thread.State: RUNNABLE                                                                                    at java.io.WinNTFileSystem.getBooleanAttributes(Native Method)    // IO overhead due to JAR file search operation                                                   at java.io.File.exists(File.java:772)                                                                                at org.jboss.vfs.spi.RootFileSystem.exists(RootFileSystem.java:99)                                                   at org.jboss.vfs.VirtualFile.exists(VirtualFile.java:192)                                                            at org.jboss.as.server.deployment.module.VFSResourceLoader$2.run(VFSResourceLoader.java:127)                         at org.jboss.as.server.deployment.module.VFSResourceLoader$2.run(VFSResourceLoader.java:124)                         at java.security.AccessController.doPrivileged(Native Method)                                                        at org.jboss.as.server.deployment.module.VFSResourceLoader.getClassSpec(VFSResourceLoader.java:124)                  at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:252)                                    at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:76)                                   at org.jboss.modules.Module.loadModuleClass(Module.java:526)                                                         at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:189)   // JBoss now fully responsible to load the class                                      at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:444) // Unchecked since using JDK 1.7 e.g. tagged as “safe” JDK                at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:432)                   at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:374)                          at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119)                                 at java.lang.Class.forName0(Native Method)                                                                            at java.lang.Class.forName(Class.java:186)                                                                           at org.jboss.tools.examples.rest.MemberResourceRESTService.AppCLFailure(MemberResourceRESTService.java:196)          at org.jboss.tools.examples.rest.MemberResourceRESTService$Proxy$_$$_WeldClientProxy.AppCLFailure(Unknown Source)    at sun.reflect.GeneratedMethodAccessor60.invoke(Unknown Source)    
……………….

上面的执行堆栈跟踪非常揭示:

  • 由于未检测到Java类名称是Java系统包的一部分,因此不会执行ClassLoader委派,因此不会进行同步。
  • 由于JBoss认为JDK 1.7+是“安全的” JDK,因此使用了ConcurrentClassLoader .performLoadClassUnchecked()方法,而不触发任何对象监视器锁定。
  • 没有同步意味着由于不间断的ClassNotFoundException错误而没有触发线程锁争用。

仍然需要注意的是,尽管在这种情况下JBoss在防止线程锁争用方面做得很出色,但是由于与过多的JAR文件搜索操作相关的IO开销,重复的类加载尝试仍会在一定程度上降低性能。加强了立即采取纠正措施的需要。

最后的话

我希望您喜欢这篇文章,并且现在对由于过多的类加载操作而可能对性能产生的影响有了更好的了解。 尽管JDK 1.7和现代Java EE容器在类加载器相关问题(例如死锁和线程锁争用)上带来了很大的改进,但仍然存在潜在的问题场景。 因此,我强烈建议您密切监视应用程序的行为,记录日志,并确保积极纠正与类加载器相关的错误,例如java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError 。

我期待您的意见,并请与Java类加载器分享您的故障排除经验。

参考: ClassNotFoundException:是否减慢了JVM的速度? 来自我们的JCG合作伙伴 Pierre Hugues Charbonneau,来自Java EE支持模式博客。

翻译自: https://www.javacodegeeks.com/2014/04/classnotfoundexception-is-it-slowing-down-your-jvm.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/342136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤教育】国家开放大学2019年春季 0752-22T建筑工程资料管理 参考试题

试卷编号&#xff1a;0752 2018——2019学年度第二学期期末考试 建筑工程资料管理 2019年6月 工程资料短期保管期限是指工程档案保存_________年以下。 技术交底分为_______________、、、_____。 单位工程档案总案卷数超过________卷的&#xff0c;应编制总目录卷。 在案卷页…

pdh光端机的优点介绍

PDH光端机&#xff08;Plesiochronous Digital Hierarchy&#xff0c;准同步数字系列&#xff09;是小容量光端机&#xff0c;一般是成对应用&#xff0c;也叫点到点应用&#xff0c;容量一般为4E1&#xff0c;8E1&#xff0c;16E1。接下来杭州飞畅科技的小编来为大家详细介绍下…

【渝粤教育】国家开放大学2019年春季 1127实用卫生统计学 参考试题

试卷代号&#xff1a;1127 2019年春季学期期末统一考试 实用卫生统计学试题&#xff08;开卷&#xff09; 2019年7月 一、单项选择题&#xff08;每题2分&#xff0c;共20分&#xff09; 1.某护士记录了50名婴儿出生体重的测定结果&#xff0c;小于2500克15人&#xff0c;介于2…

什么是485光端机,485数据光端机产品介绍

485光端机&#xff0c;光纤modem&#xff0c;485光纤收发器&#xff0c;485光端机器&#xff0c;串口光端机&#xff0c;串口转光纤&#xff0c;串口光猫&#xff0c;485光纤猫&#xff0c;提供RS-232/485/422串口转光纤功能&#xff0c;实现光纤与RS-232/485/422串口的数据双向…

OpenShift Origin中的Kubernetes Spark运算符(第1部分)

本系列有关Radanalytics.io的Kubernetes Spark运算符 OpenShift起源 。 它是一个开源的运营商来管理 Apache Spark集群和应用程序。 为了在OpenShift Origin上部署操作员&#xff0c;第一次需要为其克隆GitHub存储库&#xff1a; git clone https://github.com/radanalytics…

【渝粤教育】国家开放大学2019年春季 1312学前教育原理 参考试题

试卷代号&#xff1a;1312 学前教育原理 试题 2019年7月 一、单项选择题【每小题3分&#xff0c;共30分&#xff09; 1.学前教育学是以&#xff08; &#xff09;和学前教育问题为对象的一个研究领域。 A.幼儿园 B.学前教育现象 C.学前教育目的 D.学前教育规律 2.教育的目的不仅…

什么是模拟光端机?模拟光端机优缺点介绍!

模拟光端机是光端机的一种&#xff0c;主要是采用模拟调频、调幅、调相的方式将基带的视频、音频、数据等信号调制在某一载频上&#xff0c;通过发射光端机进行传输。传输的光信号&#xff1a;模拟光端机发射的光信号是模拟光调制信号&#xff0c;它随输入的模拟载波信号的幅度…

支付宝通知侦听器是什么_使用SWTEventHelper清除SWT侦听器通知

支付宝通知侦听器是什么为基于SWT的UI编写测试通常需要以编程方式通知小部件侦听器。 不幸的是&#xff0c;用于创建&#xff0c;初始化并最终触发事件的代码有点冗长&#xff0c;并且分散了测试的实际目的。 在编写了类似的初始化例程几次之后&#xff0c;我想出了一个小实用程…

【渝粤教育】国家开放大学2019年春季 2080现代教育思想 参考试题

试卷代号&#xff1a;2080 现代教育思想 试题&#xff08;开卷&#xff09; 注意事项 2019年7月 一、将你的学号、姓名及分校&#xff08;工作站&#xff09;名称填写在答题纸的规定栏内。考试结束后&#xff0c;把试卷和答题纸放在桌上。试卷和答题纸均不得带出考场。监考人收…

30路电话光端机

30路电话光端机就是把传统的电话信号转换成光信号并在光纤上传输的设备。30电话光端机是成对使用&#xff0c;一端去接程控交换机&#xff0c;中间是通过光纤传输&#xff0c; 另一端直接接使用电话机&#xff0c;一般是用来延长通信距离的&#xff01; 30路电话光端机采用的专…

【渝粤教育】国家开放大学2019年春季 2502学前儿童发展心理学 参考试题

试卷代号&#xff1a;2502 2 0 1 9年春季学期期末统一考试 学前儿童发展心理学 试题&#xff08;半开卷&#xff09; 2019年7月 一、选择题&#xff08;每小题2分&#xff0c;共20分&#xff09; 1&#xff0e;以时间为标准&#xff0c;在同一时间对某个年龄组或几个年龄组的儿…

工厂方法设计模式

工厂方法模式是流行的创新设计模式之一。 它并不特别依赖于工厂对象来创建对象。 相反&#xff0c;其想法是在同一类中使用单独的方法来创建对象。 Factory Method模式定义了一个用于创建对象的接口&#xff0c;但是让子类决定如何实例化其对象。 每个子类必须定义其Factory方…

【渝粤教育】国家开放大学2019年春季 2767养猪技术 参考试题

试卷代号&#xff1a;2767 养猪技术 试题 2019年7月 一、单项选择题&#xff08;每小题3分&#xff0c;共30分&#xff09; 1&#xff0e;下列不属于生产瘦猪肉的品种是( )。 A.长白猪 B&#xff0e;太湖猪 C&#xff0e;汉普夏猪 D&#xff0e;杜洛克猪 2&#xff0e;母猪的妊…

为什么单模光端机价格比多模光端机价格高

光端机的传输媒介为光纤&#xff0c;这个问题要从了解光纤光缆开始。目前常用的光纤有两大类&#xff1a;多模光纤和单模光纤。 以多模光纤制成的光缆是最早投入商用的光缆&#xff0c;由于存在色散严重、衰耗大、可用带宽窄、成本高等问题&#xff0c;已经退出了作为光缆主战…

【渝粤教育】国家开放大学2019年春季 49法律文书 参考试题

试卷代号&#xff1a;0049 座位号 2018——2019学年度第二学期期末考试 法 律 文 书 试 题 2019年7月 答题框&#xff1a; 依不同的制作方式为划分标准&#xff0c;可分为和____&#xff1f; A&#xff0e; 宣告式文书、致送式文书、信函式文书 B&#xff0e; 文叙式文书、信…

【渝粤教育】国家开放大学2019年春季 776员工招聘与管理 参考试题

试卷编号&#xff1a;0776 座位号 2018—2019年度第二学期期末考试 员工招聘与管理 试题 一、单选题&#xff08;请选出下面选项中唯一正确的答案,每小题2分&#xff0c;共20分&#xff09; 请将选择题答案填在以下表格中。 1&#xff0e;下列选项中&#xff0c;哪个选项不属…

PDH光端机常见故障及解决方法介绍

在PDH光端机的使用过程中&#xff0c;可能会出现一些影响网络的故障。那么我们该怎么去判断分析&#xff0c;并解决问题呢&#xff1f;下面&#xff0c;飞畅科技就几种PDH光端机常见故障做出分析&#xff0c;希望能帮到大家。 PDH光端机的故障可分为永久性故障和间断性故障。永…

[渝粤教育] 义乌工商职业技术学院 Python程序设计 参考 资料

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

java 文件流读取文本_如何在Java 8中处理流和读取文本文件

java 文件流读取文本我已经使用最新的Java8转换了一个旧的实用程序类。 我经常使用它来打印清单文件的内容&#xff0c;以检查任何神秘的jar文件的版本等。只需运行“ java ztools.PrintJar /path/to/my.jar”即可查看输出。 在新代码中&#xff0c;您将看到我如何使用Java 8流…

[渝粤教育] 九江学院 妇产科护理学 参考 资料

教育 -妇产科护理学-章节资料考试资料-九江学院【】 卵巢的周期性变化 女性生殖系统生理测验 1、【单选题】黄体发育的高峰期是 A、排卵前5-6天 B、排卵后5-6天 C、排卵前7-8天 D、排卵后7-8天 参考资料【 】 2、【单选题】生殖生理的叙述下列哪项是正确的 A、月经来潮时女性的…