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/364020.shtml

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

相关文章

jQuery 遍历 each()方法

输出每个 li 元素的文本&#xff1a; $("button").click(function(){$("li").each(function(){alert($(this).text())});});亲自试一试 定义和用法 each() 方法规定为每个匹配元素规定运行的函数。 提示&#xff1a;返回 false 可用于及早停止循环。 语法…

java服务器端测试_java-在服务器端测试Spring Web Services端点?

我正在使用Spring WS 2.0.我已经看到了端点和测试用例以测试端点.Endpointpublic class CustomerEndpoint {ResponsePayloadpublic CustomerCountResponse getCustomerCount(RequestPayload CustomerCountRequest request) {CustomerCountResponse response new CustomerCount…

CSS样式表的规划与组织

如果你的工作过程中遇到以下问题&#xff0c;那么请你阅读此文章。 1&#xff1a;样式表文件里面的代码混乱&#xff0c;随着项目的进展&#xff0c;样式表里面的先有代码不敢做任何改变&#xff0c;因为连自己也不知道改了以后会给现有项目造成什么影响。更不敢删除。因为连自…

【链接】Linux C/C++ 学习路线-已拿腾讯、百度 offer

https://www.nowcoder.com/discuss/203082?type0&order0&pos69&page1 https://www.nowcoder.com/discuss/193598 https://www.nowcoder.com/discuss/164781 https://www.nowcoder.com/discuss/188367 https://www.nowcoder.com/discuss/188367 已经有两年C经验的话…

游戏文本本地化(一)

游戏中常见的文本本地化一般包括以下几项: 1、代码 --- 即直接写在代码中的文本 2、配置表 --- 主要由策划配置 3、UIPrefab --- 制作预设在Label上直接写入的文本 4、图片字 --- 包括 UIPrefab、UI 特效上的美术字 5、新手引导 --- 主要由配置新手引导的相关人员产生 6、错误码…

Dropwizard:轻松的RESTful JSON HTTP Web服务

寻求快速&#xff0c; 轻松地创建可用于生产环境的RESTful JSON HTTP Web服务的Java开发人员应该考虑Dropwizard框架。 Dropwizard汇集了相互补充的广受好评的库&#xff0c;因此您可以了解重要的内容&#xff1a;编写和交付工作代码。 对于那些对所用库的详细信息感兴趣的人&a…

split 将字符串分割成字符串数组

list_name list_name.split(","); split() 方法用于把一个字符串分割成字符串数组。 语法 stringObject.split(separator,howmany) 参数描述separator 必需。字符串或正则表达式&#xff0c;从该参数指定的地方分割 stringObject。howmany …

python可以自动写文章吗_让python来告诉你神奇的操作,如何实现文章自动化

三河讲python首先来告诉大家下面的Python程序实现了通过从网页抓取一篇文章&#xff0c;然后根据这篇文章来生成新的文章&#xff0c;这其中的原理就是基于概率统计的文本分析。过程大概就是网页抓取数据->统计分析->生成新文章。网页抓取数据是通过BeautifulSoup库来抓取…

badboy的录制和jmeter的使用

v Jmeter是什么 Apache Jmeter是Apache组织开发的基于Java的压力测试工具。Jmeter可以用于对服务器、网络或对象模拟巨大的负载&#xff0c;来自不同压力类别下测试它们的强度和分析整体性能。另外&#xff0c;Jmeter能够对应用程序做功能、回归测试&#xff0c;通过创建带有断…

一张图看懂offsetX, clientX, pageX, screenX的区别

1.具体含义见下图1 2.浏览器的兼任情况 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

接口一个被我忽略的地方--接口重定向技术

习惯于用IDE生成接口方法了,右键点击"Implement Interface",生成所有的接口方法声明,还带个Region多方便啊.今天看<<CLR Vir C#>>时才了解到自己是知其然不知其所有然啊. 实现接口方法很简单,新手估计也都会,但怎么理解这个过程,不见得所有人都知道 Base…

java extends throws_继承,方法签名,方法重写和throws子句

容易记住访问修饰符可以从限制更改为限制更少&#xff0c;例如从受保护到公共&#xff0c;但反之亦然throws签名可以是从父异常更改为子异常类&#xff0c;但反之亦然此代码有效public class A {protected String foo() throws Exception{return "a";}class B extend…

[BZOJ]4071: [Apio2015]巴邻旁之桥

题解: 首先 明确 如果处于同一区域时 直接统计贡献即可 不用过桥 对k分情况讨论: 当k1时 假设桥的位置是 p 那么 $$ \sum_{i1}^n |x_i-p||y_i-p| $$ 很显然当对于 所有x,y排序后的中位数是最优的选择位置 具体证明可以模拟一下 当k2时 假设桥的位置是$p_1$和$p_2$ $$ \su…

vue 学习之路 —— 图片的引入

问题记录&#xff1a;在img中动态设置了src后&#xff0c;图片路径找不到 原因&#xff1a;vue中动态生成的路径无法被url-loader解析到 解决方法&#xff1a; 1、将图片放在static文件夹&#xff0c;然后正常解析 2、将图片使用import方法引入 3、 采用背景图做法&#xff0c;…

跟踪异常–第5部分–使用Spring进行计划

看来我终于快要结束本系列有关使用Spring进行错误跟踪的博客了&#xff0c;对于那些还没有阅读该系列博客的人&#xff0c;我正在编写一个简单但几乎具有工业实力的Spring应用程序&#xff0c;扫描日志文件中的异常&#xff0c;然后生成报告。 在本系列的第一个博客中&#xff…

java.util.hashmap_java.util.HashMap中的无限循环

我在这里经常有一些Vaadin代码阻塞,我不知道问题是什么&#xff1a;Thread 7892: (state IN_JAVA)- java.util.HashMap.getEntry(java.lang.Object) bci61, line349 (Compiled frame; information may be imprecise)- java.util.HashMap.containsKey(java.lang.Object) bci2, …

APP测试理论知识点

什么是APP测试&#xff1f; App测试就是软件工程师对这类应用软件进行功能测试&#xff0c;性能测试&#xff0c;安全性测试以及兼容性测试等。 对于app测试我们一般采用的是黑盒测试方法&#xff0c;也会在必要的时候进行自动化测试以及性能测试&#xff0c;丙炔对于app还会有…

超大超长图片居中显示且放大缩小无影响

1. 超大图片居中显示 1.1 放大缩小都居中显示 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>Document</title><style>body {overflow-x: hidden;}.top-banner .banner-list a {display: b…

蘋果的秘密武器

蘋果公司(Apple)在電腦操作平台之戰中負於微軟公司 (Microsoft)已經過去很多年了。如今﹐90%以上的筆記本電腦和台式電腦在使用微軟的Windows操作系統。然而近幾年來﹐蘋果公司對Windows主宰的世界發起突然襲擊﹐它的武器就是Windows版的iTunes﹐一個免費的媒體管理、儲存和播放…

如何使用NodeManager来控制WebLogic Server

在上一篇文章中 &#xff0c;您已经了解了如何启动WebLogic管理员和多个托管服务器。 该指令的一个缺点是这些进程将从前台开始&#xff0c;而STDOUT则打印在终端上。 如果打算将这些服务器作为后台服务运行&#xff0c;则可能需要尝试使用WebLogic节点管理器wlscontrol.sh工具…