Unisafe.defineClassにかけられた-反射速度が遅い実戦事例
5455 ワード
Usafe.defineClassをかけます。反射速度が遅いです。
Java 8/SpringBoot 1.5113/Tomcat 8.5 Webアプリケーションにおいて、動作時間が極めて長い要求が観測された(>30s)。そして、カートン時間はプログラムの運行時間とともに長くなります。しかし、ほとんどの要求の応答は正常である。カートン発生時のcpu負荷は100%まで増加し、数分後に自分で下がります。
ThreaddumpsはUnisafe.defineClassが掛かっていると表示します。
返信
「バカなあなた」:これらの出力を見ると、主に一つのagentを載せてクラスを操作しています。正常な環境からこのagentを削除することを提案します。理論的にロードされているクラスはほぼ全部ロードされています。この問題はなくなります。
異なる仮想マシンバージョンの下の-XX:+Trace Class Uniloadingについて
JDK 8でクラスのアンインストールを再現する例を試みましたが、このパラメータを加えるとコンソールに対応するunloadログ出力が見られません。TraceClass UloadingはJDK 9後に使用することを推奨しないので、-Xlogs:class+unload=infoに置き換えられます。同じコードはJDK 9(macos環境makeコンパイル)、JDK 11で、新しいパラメータの下で、対応するunloadログを見ることができます。なぜですかテストコードは以下の通りです
[大空翼]:Loop.classという類の経路も/Users/mozara/core/universe/java-base/target/clases/?もしその位置だったら、appclassloaderがロードしたかもしれません。それではアンインストールできません。compを作ってみてもいいです。comp.github.universe.java.base.Powの類のキャリアはどれですか?
[Mozilla]:同じCLに等しいと生きていると、確実にunloadできません。しかし、上記のように、コードはClass Loader Bにロードさせるように指定されています。そしてロードが成功したら、私もロゴマークを出してコンサートでソロします。それに同じコードJDK 8はJDK 9,11でいいです。
[空翼]:Class Loaderの委託類のローディング機構は、必ずしもあなたが指定したこの種類のキャリアローディングではなく、親に委託することができます。タイトルをクリックして答えを確認してください。
おすすめの読書
JVMソース分析のスタックオーバーフロー完全解読
おすすめの読書
GCの実戦―フローティングメモリによるCPUの高すぎる調整
Java 8/SpringBoot 1.5113/Tomcat 8.5 Webアプリケーションにおいて、動作時間が極めて長い要求が観測された(>30s)。そして、カートン時間はプログラムの運行時間とともに長くなります。しかし、ほとんどの要求の応答は正常である。カートン発生時のcpu負荷は100%まで増加し、数分後に自分で下がります。
ThreaddumpsはUnisafe.defineClassが掛かっていると表示します。
"http-nio-8080-exec-9" #254 daemon prio=5 os_prio=0 tid=0x00007f8a98b4f000 nid=0x2258 runnable [0x00007f89fb0b0000]
java.lang.Thread.State: RUNNABLE
at sun.misc.Unsafe.defineClass(Native Method)
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
at sun.reflect.MethodAccessorGenerator.generateMethod(MethodAccessorGenerator.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:53)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:618)
at org.springframework.beans.BeanUtils.copyProperties(BeanUtils.java:538)
at com.haigui.stateaction.action_impl.DisputeSubmit.insertDisputeInfo(DisputeSubmit.java:128)
カートン発生時のJVM状況:返信
「バカなあなた」:これらの出力を見ると、主に一つのagentを載せてクラスを操作しています。正常な環境からこのagentを削除することを提案します。理論的にロードされているクラスはほぼ全部ロードされています。この問題はなくなります。
異なる仮想マシンバージョンの下の-XX:+Trace Class Uniloadingについて
JDK 8でクラスのアンインストールを再現する例を試みましたが、このパラメータを加えるとコンソールに対応するunloadログ出力が見られません。TraceClass UloadingはJDK 9後に使用することを推奨しないので、-Xlogs:class+unload=infoに置き換えられます。同じコードはJDK 9(macos環境makeコンパイル)、JDK 11で、新しいパラメータの下で、対応するunloadログを見ることができます。なぜですかテストコードは以下の通りです
public class Loop {
public static void main(String[] args) throws Exception{
ClassLoaderB loaderB = new ClassLoaderB("CLB");
loaderB.setPath("/Users/mozilla/core/universe/java-base/target/classes/");
Class> clazz = loaderB.loadClass("com.github.universe.java.base.Pow");
Object object = clazz.newInstance();
System.out.println(object);
System.out.println("-----------------");
loaderB = null;
clazz = null;
object = null;
System.gc();
// System.gc();
while (true){
Thread.sleep(100000);
}
}
private static class ClassLoaderA extends ClassLoader{}
private static class ClassLoaderB extends ClassLoader {
private String classLoaderName;
//
private final String fileExtension = ".class";
private String path;
public void setPath(String path) {
this.path = path;
}
public ClassLoaderB(String classLoaderName) {
super();
this.classLoaderName = classLoaderName;
}
public ClassLoaderB(String classLoaderName, ClassLoader parent) {
super(parent);
this.classLoaderName = classLoaderName;
}
@Override
protected Class> findClass(String className) throws ClassNotFoundException {
System.out.println("findClass invoked: " + className);
System.out.println("class loader name: " + this.classLoaderName);
byte[] data = this.loadClassDate(className);
return this.defineClass(className, data, 0, data.length);
}
private byte[] loadClassDate(String name) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try {
name = name.replace(".", "/");
is = new FileInputStream(new File(this.path + name + this.fileExtension));
baos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
}
}
返信[大空翼]:Loop.classという類の経路も/Users/mozara/core/universe/java-base/target/clases/?もしその位置だったら、appclassloaderがロードしたかもしれません。それではアンインストールできません。compを作ってみてもいいです。comp.github.universe.java.base.Powの類のキャリアはどれですか?
[Mozilla]:同じCLに等しいと生きていると、確実にunloadできません。しかし、上記のように、コードはClass Loader Bにロードさせるように指定されています。そしてロードが成功したら、私もロゴマークを出してコンサートでソロします。それに同じコードJDK 8はJDK 9,11でいいです。
[空翼]:Class Loaderの委託類のローディング機構は、必ずしもあなたが指定したこの種類のキャリアローディングではなく、親に委託することができます。タイトルをクリックして答えを確認してください。
おすすめの読書
JVMソース分析のスタックオーバーフロー完全解読
おすすめの読書
GCの実戦―フローティングメモリによるCPUの高すぎる調整