簡體   English   中英

NoClassDefFoundError java.lang包中的類的“錯誤名稱”

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

我在主機上運行Cassandra 2.2.11(並且不會升級)。 我在cron作業中定期運行nodetool命令進行監控。 nodetool實現為另一個使用JMX與Cassandra java進程通信的java進程。 我每分鍾發出五個左右的命令。

偶爾(不是任何可識別的模式), nodetool的執行將失敗, NoClassDefFoundError引用java.lang的類。 例如,

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)

在此堆棧跟蹤中,在FutureTask類初始化期間發生錯誤。 我也見過

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)
    [...]

但是也

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)
    [...]

所以它不僅發生在類初始化期間,而且,在我收集的少量樣本中,反射實現中的某些東西似乎確實是罪魁禍首。

Java版本為8

java version "1.8.0_144"

nodetool啟動程序始終使用相同的類路徑。 並且沒有奇怪的類(或其他類加載器)。 在數百個相同的節點上(在Linux上)完成相同的安裝。

我對NoClassDefFoundError wrong name最佳搜索結果是指使用簡化類名來啟動java而不是完全限定名稱的執行。 這不是問題所在。 此外,錯誤消息中的名稱是相同的。

那么什么會導致“bootstrap”類的“錯誤名稱” NoClassDefFoundError錯誤?

我認為缺乏資源導致連接器超時等問題。 你看到你的例子中的日志嗎? nodeprobe是通過jmx連接還是嘗試連接然后發生錯誤? 這些是非常典型的錯誤,也可能導致其他間歇錯誤。(通常是OS / netowrk OS shit)因此:包括你的字符串甚至基於對象的錯誤;總之它是有道理的。 可能是您應該在錯誤發生時檢查您的資源。 我知道資源監視器導致缺乏資源,這有點像22; 但它發生了嘿嘿

由於沒有找到基本的java庫,我認為你的java安裝存在問題,或者你沒有設置CLASSPATHJAVA_HOME環境變量。 嘗試設置CLASSPATHJAVA_HOME環境變量。

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

如果不起作用,請嘗試重新安裝java並設置環境變量。

根據stacktraces,在調用getDeclaredFields0拋出異常id。 但是,這不是最初的例外。 根據OpenJDK源代碼,代碼庫中沒有任何內容在異常消息中拋出“錯誤名稱”的異常。 消息來自其他地方。

我強烈懷疑這實際上是在重新報告第一次加載或初始化某個類時發生的問題。 會發生的是,類加載器第一次發現問題,將違規的內部類對象標記為“壞”,然后拋出錯誤。 根據javadoc,應用程序不應該嘗試從中恢復。 但如果有人這樣做,然后嘗試以某種方式使用“壞”類,原始問題將再次報告為原始原因的NoClassDefFoundError

那么原因是什么意思呢?

很難分辨,因為我們沒有原始異常的堆棧跟蹤; 即然后是類加載/初始化首次失敗的那個。 如果你能找到堆棧跟蹤,我們可以找到執行的第三方庫。 它幾乎肯定發生在類加載器中。

明顯的含義是類文件中的類名與類字節碼中的名稱不匹配。 但是,我們需要檢查類加載器代碼以確保。

那為什么間歇性地發生呢?

可能是因為應用程序JVM有許多類加載器,並且只有它們的一部分已經用這個壞類“污染”了它們的類命名空間。

這可能是壞消息。 它表明應用程序的核心可能存在某種同步問題。

無論如何,沒有足夠的證據可以得出合理的結論。

底線

根據證據,我這是某種“代碼編織”或“字節碼工程”出錯的結果。 作為進一步的猜測 ,我會說一些子類加載器沒有正確委托,並且錯誤地嘗試處理內置類。 (甚至可能是有問題的類加載器知道它應該永遠不會處理“java.lang。*”類,並且它有一種模糊的說法。)

為什么? 可能是因為有人/某事物明確地將“rt.jar”添加到了一些不應該出現的類路徑中。

為了進一步診斷,我們首先需要的是原始的堆棧跟蹤,它告訴我們哪個類加載器完成了初始損壞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM