为什么Unsafe.defineClass CPU占用率高

问题描述 投票:0回答:1

在 Java 8 / SpringBoot/Tomcat Web 应用程序中观察到运行时间极长的请求(> 30 秒)。并且滞后时间会随着程序运行时间的延长而增加。但大多数请求的响应都是正常的。延迟时 CPU 负载增加到 100%,然后在几分钟后自行下降。

Threaddumps 显示 unsafe.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)

pstack 输出调用堆栈如下

Thread 70 (Thread 0x7f0a0119f700 (LWP 18563)):
0x00007f0a5f43dlf8 JvmtiEnv: :GetThreadLocalStorage(_jobject*, void**) () from /usr/local/jdkl.8.0_231/jre/lib/amd64/ser..
0x00007f09ffa882b2 in assertTLSValue () from /usr/local/jdkl.8.0_231/j re/Lib/amd64/libinstrument.so
0x00007f09ffa88427 in releaseReentrancyToken () from /usr/local/jdkl.8.0_231/j re/Lib/amd64/libinstrument.so
0x00007f09ffa86044 in transformClassFile () from /usr/local/jdkl.8.0_231/jre/lib/amd64/libinstrument.so
0x00007f09ffa84eef in eventHandlerClassFileLoadHook () from /usr/local/jdkl.8.0_231/jre/lib/amd64/libinstrument.so
0x00007f0a5f461512 in JvmtiClassFileLoadHookPoster:: post_to_env(JvmtiEnv*, bool) () from /usr/local./idkl.8.0_231/i re/lib/am
0x00007f0a5f453a65 in JvmtiExport::post_class_file_load_hook(Symbol*, Handle, Handle, unsigned char**, unsigned char**, Jvm
0x00007f0a5fll964c in ClassFileParser: :parseClassFile(Symbol.*, ClassLoaderData*, Handle, KlassHandle, GrowableArray<Handle> 
0x00007f0a5f722107 in SystemDictionary::resolve_from_stream(Symbol*, Handle, Handle, ClassFilestream*, bool, Thread*) () fr
0x00007f0a5f3d4f33 in jvm_define_class_common(JNIEnv_*, char const*, _jobject*, signed char const*, int, _jobject*, char co
0x0O007f0a5f3d658a in JVM_DefineClass () from /usr/local/jdkl.8.0_231/j re/lib/amd64/server/libivm.so
0x00007f0a5f77ae4b in Unsafe_DefineClass_impl(JNIEnv_*, _jstring*, _jbyteArray*f int, int, [object*, _jobject*) () from /u
0x00007f0a5f77e3b9 in Unsafe_DefineClass () from /usr/local/jdkl.8.0_231/jre/lib/amd64/server/libjvm.so
0x00007f0a492677cb in ?? 0
0x0O007f0a01199d28 in ??()
0x0000000000000000 in ??()
java spring reflection jvm
1个回答
0
投票

使用 MethodHandles.Lookup#defineClass(byte[]) 代替

sun.misc.Unsafe.defineClass 已弃用

我认为,如果您监控 RAM 或存储空间,您会发现其中一个几乎已满,这就是为什么需要这么长时间的原因。

© www.soinside.com 2019 - 2024. All rights reserved.