简体   繁体   English

NoClassDefFoundError java.lang包中的类的“错误名称”

[英]NoClassDefFoundError “wrong name” for a class in the java.lang package

I'm running Cassandra 2.2.11 (and won't be upgrading) on a host. 我在主机上运行Cassandra 2.2.11(并且不会升级)。 Periodically, in a cron job, I run nodetool commands for monitoring. 我在cron作业中定期运行nodetool命令进行监控。 nodetool is implemented as just another java process that uses JMX to talk to the Cassandra java process. nodetool实现为另一个使用JMX与Cassandra java进程通信的java进程。 I launch five or so commands every minute. 我每分钟发出五个左右的命令。

Once in a while (not in any recognizable pattern), the execution of nodetool will fail with a NoClassDefFoundError that refers to a class from java.lang . 偶尔(不是任何可识别的模式), nodetool的执行将失败, NoClassDefFoundError引用java.lang的类。 For example, 例如,

java.lang.NoClassDefFoundError: java/lang/Thread (wrong name: java/lang/Thread)
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredField(Class.java:2068)
    at java.util.concurrent.FutureTask.<clinit>(FutureTask.java:476)
    at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleWithFixedDelay(ScheduledThreadPoolExecutor.java:590)
    at sun.rmi.transport.tcp.TCPChannel.free(TCPChannel.java:347)
    at sun.rmi.server.UnicastRef.free(UnicastRef.java:431)
    at sun.rmi.server.UnicastRef.done(UnicastRef.java:448)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:132)
    at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:205)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1955)
    at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1922)
    at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:287)
    at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
    at org.apache.cassandra.tools.NodeProbe.connect(NodeProbe.java:183)
    at org.apache.cassandra.tools.NodeProbe.<init>(NodeProbe.java:150)
    at org.apache.cassandra.tools.NodeTool$NodeToolCmd.connect(NodeTool.java:302)
    at org.apache.cassandra.tools.NodeTool$NodeToolCmd.run(NodeTool.java:242)
    at org.apache.cassandra.tools.NodeTool.main(NodeTool.java:158)

In this stack trace, the error happens during class initialization for FutureTask . 在此堆栈跟踪中,在FutureTask类初始化期间发生错误。 I've also seen 我也见过

java.lang.NoClassDefFoundError: java/lang/Object (wrong name: java/lang/Object)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.getDeclaredMethod(Class.java:2128)
    at java.lang.invoke.MethodHandleImpl$Lazy.<clinit>(MethodHandleImpl.java:614)
    [...]

but also 但是也

java.lang.NoClassDefFoundError: java/lang/String (wrong name: java/lang/String)
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredField(Class.java:2068)
    at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1703)
    at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:72)
    at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:484)
    at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:472)
    [...]

So it's not only happening during class initialization, but, in the few samples I've collected, something in the reflection implementation does seem to be the culprit. 所以它不仅发生在类初始化期间,而且,在我收集的少量样本中,反射实现中的某些东西似乎确实是罪魁祸首。

Java is at version 8 Java版本为8

java version "1.8.0_144"

The nodetool launcher always uses the same classpath. nodetool启动程序始终使用相同的类路径。 And there are no weird classes in there (or additional class loaders). 并且没有奇怪的类(或其他类加载器)。 The same installation is done across hundreds of identical nodes (on Linux). 在数百个相同的节点上(在Linux上)完成相同的安装。

My top search results for NoClassDefFoundError wrong name refer to executions where a simplified class name was used to launch java , rather than the fully qualified name. 我对NoClassDefFoundError wrong name最佳搜索结果是指使用简化类名来启动java而不是完全限定名称的执行。 That's not the issue here. 这不是问题所在。 Also, the names in the error messages are identical. 此外,错误消息中的名称是相同的。

So what can cause such "wrong name" NoClassDefFoundError errors for "bootstrap" classes? 那么什么会导致“bootstrap”类的“错误名称” NoClassDefFoundError错误?

i think it is the lack of resource that cause the problems like the connector timeout or something. 我认为缺乏资源导致连接器超时等问题。 Do you see the log from your example?; 你看到你的例子中的日志吗? nodeprobe is connecting through the jmx or trying to connect then the error occurs? nodeprobe是通过jmx连接还是尝试连接然后发生错误? Those are very typical error that can also cause other intermiten error on the shit.(usually OS/netowrk OS shit) thus : includes your string and even object based error ;in conclusion it make sense. 这些是非常典型的错误,也可能导致其他间歇错误。(通常是OS / netowrk OS shit)因此:包括你的字符串甚至基于对象的错误;总之它是有道理的。 may be you should check your resource when the error happen. 可能是您应该在错误发生时检查您的资源。 i know this is kind of catch 22 that the resource monitor is causing the lack of resource instead; 我知道资源监视器导致缺乏资源,这有点像22; but it happen hehe 但它发生了嘿嘿

As none of basic java library found,I think there is problem in your java installation or you have not set CLASSPATH and JAVA_HOME environment variables. 由于没有找到基本的java库,我认为你的java安装存在问题,或者你没有设置CLASSPATHJAVA_HOME环境变量。 Try to set CLASSPATH and JAVA_HOME environment variables. 尝试设置CLASSPATHJAVA_HOME环境变量。

export JAVA_HOME="/usr/lib/jvm/java-8-oracle/bin"
export CLASSPATH="/usr/lib/jvm/java-8-oracle/lib"

If not worked, try reinstall java and set environment variables. 如果不起作用,请尝试重新安装java并设置环境变量。

According to the stacktraces, the exception id being thrown in a calls to getDeclaredFields0 . 根据stacktraces,在调用getDeclaredFields0抛出异常id。 However, this is not where the exception came from originally. 但是,这不是最初的例外。 According to the OpenJDK source code, there is nothing in the codebase that throws an exception with "wrong name" in the exception message. 根据OpenJDK源代码,代码库中没有任何内容在异常消息中抛出“错误名称”的异常。 The message has come from somewhere else. 消息来自其他地方。

I strongly suspect that this is actually re-reporting a problem that happened the first time that some class was loaded or initialized. 我强烈怀疑这实际上是在重新报告第一次加载或初始化某个类时发生的问题。 What happens is that the classloader finds the problem the first time, marks the offending internal class object as "bad" and then the throws the error. 会发生的是,类加载器第一次发现问题,将违规的内部类对象标记为“坏”,然后抛出错误。 According to the javadoc, applications should not attempt to recover from this. 根据javadoc,应用程序不应该尝试从中恢复。 But if one does, and then attempts to use the "bad" class in some way, the original problem will be reported again as a NoClassDefFoundError with the original reason. 但如果有人这样做,然后尝试以某种方式使用“坏”类,原始问题将再次报告为原始原因的NoClassDefFoundError

So what does the reason mean? 那么原因是什么意思呢?

It is hard to tell because we don't have the stacktrace for the original exception; 很难分辨,因为我们没有原始异常的堆栈跟踪; ie then one where the classloading / initialization first failed. 即然后是类加载/初始化首次失败的那个。 If you can find that stacktrace, we can track down the 3rd-party library that did it. 如果你能找到堆栈跟踪,我们可以找到执行的第三方库。 It is almost certainly happening in a classloader. 它几乎肯定发生在类加载器中。

The obvious meaning is that a class file has a classname in it that doesn't match the name in the classes bytecodes. 明显的含义是类文件中的类名与类字节码中的名称不匹配。 However, we'd need to examine the classloader code to be sure. 但是,我们需要检查类加载器代码以确保。

So why is it happening intermittently? 那为什么间歇性地发生呢?

Possibly because the application JVM has many classloaders and only a subset of them have "polluted" their class namespace with this bad class. 可能是因为应用程序JVM有许多类加载器,并且只有它们的一部分已经用这个坏类“污染”了它们的类命名空间。

That could be bad news. 这可能是坏消息。 It suggests there may be some kind of synchronization issue in the core of the application. 它表明应用程序的核心可能存在某种同步问题。

Anyhow, there is not enough evidence to draw sound conclusions. 无论如何,没有足够的证据可以得出合理的结论。

Bottom line 底线

Based on the evidence, I would guess that this is a result of some kind of "code weaving" or "byte code engineering" that has gone wrong. 根据证据,我这是某种“代码编织”或“字节码工程”出错的结果。 As a further guess , I would say that some child classloader is not delegating properly, and has mistakenly attempted to process a built-in class. 作为进一步的猜测 ,我会说一些子类加载器没有正确委托,并且错误地尝试处理内置类。 (It could even be that the classloader in question knows that it should never process a "java.lang.*" class and it has a obscure way of saying this.) (甚至可能是有问题的类加载器知道它应该永远不会处理“java.lang。*”类,并且它有一种模糊的说法。)

Why? 为什么? possibly because someone / something explicitly added the "rt.jar" to some classpath that it shouldn't be on. 可能是因为有人/某事物明确地将“rt.jar”添加到了一些不应该出现的类路径中。

For further diagnosis, the first thing we need is the original stacktrace that tells us which classloader did the initial damage. 为了进一步诊断,我们首先需要的是原始的堆栈跟踪,它告诉我们哪个类加载器完成了初始损坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM