Jetty によって実行される非常に小さな Web サービス (1,000 行未満のコード) があります。ストレステストの段階でも、サービスは常に正常に機能しました。ただし、13 日間のアップタイムの後、同じ日に 2 つのノードで ClassNotFoundException が発生しました。
奇妙なことは、見つからなかったクラスが既に存在していたことです (これはスタートアップ ルーチンの一部であり、以前の要求を処理するために常に使用されていました)。実際、プロセスを再起動するだけで問題は解決しました。両方のノードは別々のマシンにあり、互いに独立しています。1 つの JMS 接続を除いて、外部リソースに依存しません。
報告された問題のほとんどは、Java プロセスの起動中にクラス パスにクラスが見つからないことに関連しているため、これをグーグルで検索しているときに関連情報を見つけることができませんでした。これは私たちのケースではありません。JVM メモリを何らかの形で破壊するメモリ リークが発生した可能性があると思われますが、2 つのノードでほぼ同時に同じ問題が発生した理由を説明することはできません。過去 5 日間、JVM モニターとメモリ リーク アナライザーを接続して集中的なストレス テストを実行してきましたが、すべて問題ないようです。このテストでは、プロセス メモリを 2GB から 512MB に減らしました。
詳細:
- Java HotSpot(TM) 64 ビット サーバー VM の使用 (ビルド 16.3-b01、混合モード)
- jetty-runner-8.1.0.RC5.jar の使用
- 元のコマンドライン: java -Xmx2048M -jar jetty-runner-8.1.0.RC5.jar --port 5000 webapp.war
- Intel Xeon E5-2680 8 コア (x2) + 16GB RAM
- レッドハット エンタープライズ リナックス 6
- 使用中のフレームワーク: JBoss Resteasy、Spring IoC、Guava。
JVM が以前にロードされたクラスの存在を突然「忘れ」、再度ロードできなくなる原因について、アイデアを提供していただけませんか?
Caused by: java.lang.ClassNotFoundException: com.a.b.c.SomeClass
at java.net.URLClassLoader$1.run(URLClassLoader.java:202) ~[na:1.6.0_37]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_37]
at java.net.URLClassLoader.findClass(URLClassLoader.java:190) ~[na:1.6.0_37]
at java.lang.ClassLoader.loadClass(ClassLoader.java:306) ~[na:1.6.0_37]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) ~[na:1.6.0_37]
at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[na:1.6.0_37]
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:424) ~[na:na]
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377) ~[na:na]
at java.lang.Class.forName0(Native Method) ~[na:1.6.0_37]
at java.lang.Class.forName(Class.java:247) ~[na:1.6.0_37]
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:95) ~[na:1.6.0_37]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:107) ~[na:1.6.0_37]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:31) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:370) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:351) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:280) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:222) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69) ~[na:1.6.0_37]
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52) ~[na:1.6.0_37]
at java.lang.reflect.Field.declaredAnnotations(Field.java:1014) ~[na:1.6.0_37]
at java.lang.reflect.Field.getDeclaredAnnotations(Field.java:1007) ~[na:1.6.0_37]
編集:
WinでNFSマウントを使用しているときに、JVMがクラスをアンロードすることを決定し、必要に応じて再ロードする可能性があると誰かが私に言いました。このプロセスの途中で NFS 接続が切断された場合、ファイル ハンドルは無効になり、再ロードは同様のスタック トレースで失敗します。私たちの場合、Linux を使用しており、関連するすべてのファイルは同じマウント (ローカル ハードディスク) にあります。さらにテストを行うために、Jetty 一時ディレクトリに CD を作成し、特定のサービス クラスでよく知られているディレクトリを手動で削除しました。JVM がそれをアンロードしてからクラス ディレクトリから再ロードしようとすると、失敗します。これは元の問題を説明するものではありませんが、より多くの情報がテーブルに表示される可能性があります...