如果一个线程调用 getStackTrace() 并且 lambda 定义(通过 Unsafe.defineAnonymousClass)发生在另一线程中,则 Java8 挂起

2024-05-02

我的 Web 应用程序在 Apache Tomcat/8.0.21、JVM 1.8.0_45-b15 和 Windows Server 2012 上运行,运行在 16 核(32 个带 HT)双 Xeon NUMA 计算机上,在某些非常不幸的情况下可能会卡住情况下,当标题中描述的操作同时发生在两个不同的线程中时。

执行第一个操作的线程 (getStackTrace())正在尝试执行一些诊断来检测系统的哪个部分正在减慢速度并在调用时卡住Thread.dumpThreads。 另一个线程正在执行一些操作,其中包括 JVM 部分的底层 lambda 定义。

特别是,我有以下堆栈跟踪(通过jstack -F <pid>):

Attaching to process ID 6568, please wait... 
Debugger attached successfully. 
Server compiler detected. 
JVM version is 25.45-b02 

Deadlock Detection:

No deadlocks found. (... well, that's not the kind of deadlock you were searching for, dear JVM, but something bad is happening altogether :( )

Thread 155: (state = BLOCKED)
 - sun.misc.Unsafe.defineAnonymousClass(java.lang.Class, byte[], java.lang.Object[]) @bci=0 (Compiled frame; information may be imprecise)
 - java.lang.invoke.InvokerBytecodeGenerator.loadAndInitializeInvokerClass(byte[], java.lang.Object[]) @bci=8 (Compiled frame)
 - java.lang.invoke.InvokerBytecodeGenerator.loadMethod(byte[]) @bci=6 (Compiled frame)
 - java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCode(java.lang.invoke.LambdaForm, java.lang.invoke.MethodType) @bci=17 (Compiled frame)
 - java.lang.invoke.LambdaForm.compileToBytecode() @bci=65 (Compiled frame)
 - java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(java.lang.invoke.MethodType, int) @bci=638 (Interpreted frame)
 - java.lang.invoke.DirectMethodHandle.preparedLambdaForm(java.lang.invoke.MethodType, int) @bci=17 (Compiled frame)
 - java.lang.invoke.DirectMethodHandle.preparedLambdaForm(java.lang.invoke.MemberName) @bci=163 (Compiled frame)
 - java.lang.invoke.DirectMethodHandle.make(byte, java.lang.Class, java.lang.invoke.MemberName) @bci=94 (Compiled frame)
 - java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(byte, java.lang.Class, java.lang.invoke.MemberName, boolean, boolean, java.lang.Class) @bci=201 (Compiled frame)
 - java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(byte, java.lang.Class, java.lang.invoke.MemberName, java.lang.Class) @bci=8 (Compiled frame)
 - java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(byte, java.lang.Class, java.lang.invoke.MemberName) @bci=30 (Compiled frame)
 - java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(byte, java.lang.Class, java.lang.String, java.lang.Object) @bci=115 (Compiled frame)
 - java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(java.lang.Class, int, java.lang.Class, java.lang.String, java.lang.Object) @bci=38 (Compiled frame)
 - c.e.s.w.t.si.a.DDVP.lambda$1(com.vaadin.data.Container, com.vaadin.ui.HorizontalLayout, com.vaadin.ui.Label, com.vaadin.ui.Label, java.lang.String, java.lang.String, java.util.Map) @bci=48, line=104 (Interpreted frame)
 - c.e.s.w.t.si.a.DDVP$$Lambda$637.updateUIWith(java.lang.Object) @bci=32 (Interpreted frame)
 - c.e.s.w.d.DU$VoidUIUpdaterFromUIUpdater.updateUI() @bci=8, line=321 (Compiled frame)
 - c.e.s.w.d.DU$CompletionSignallingVoidUIUpdater.updateUI() @bci=4, line=125 (Compiled frame)
 - c.e.s.w.d.CUQ$1.sweepWhileNotTimedOut() @bci=59, line=218 (Compiled frame)
 - c.e.s.w.d.CUQ$QueueExhauster.run() @bci=247, line=122 (Compiled frame)
 - c.e.s.w.d.CUQ$DequeuerStartFailed.run() @bci=40, line=60 (Compiled frame)
 - c.e.s.w.s.ew.CC.lambda$4(java.lang.Runnable) @bci=13, line=66 (Compiled frame)
 - c.e.s.w.s.ew.CC$$Lambda$59.run() @bci=8 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5 (Interpreted frame)
 - java.lang.Thread.run() @bci=11 (Compiled frame)

Thread 108: (state = BLOCKED) [The tricky one...]
 - java.lang.Thread.dumpThreads(java.lang.Thread[]) @bci=0 (Interpreted frame)
 - java.lang.Thread.getStackTrace() @bci=41 (Compiled frame)
 - c.e.s.w.SWA$$Lambda$98.getStackTrace() @bci=4 (Interpreted frame)
 - c.e.s.w.SWA.describeHoggingCode(c.e.s.w.s.RequestTimeTracker$StackTraceProvider, boolean) @bci=1, line=401 (Interpreted frame)
 - c.e.s.w.SWA.describeHoggingCode(c.e.s.w.s.RequestTimeTracker$StackTraceProvider, boolean, java.lang.Thread) @bci=6, line=396 (Interpreted frame)
 - c.e.s.w.SWA.lambda$10(java.lang.Thread, java.lang.String) @bci=8, line=890 (Interpreted frame)
 - c.e.s.w.SWA$$Lambda$62.run() @bci=12 (Interpreted frame)
 - c.e.s.w.s.ew.CC.lambda$4(java.lang.Runnable) @bci=13, line=66 (Compiled frame)
 - c.e.s.w.s.ew.CC$$Lambda$59.run() @bci=8 (Compiled frame)
 - c.e.s.w.s.IS.lambda$4(java.util.concurrent.atomic.AtomicBoolean, java.lang.Runnable) @bci=8, line=327 (Compiled frame)
 - c.e.s.w.s.IS$$Lambda$60.run() @bci=8 (Compiled frame)
 - java.util.concurrent.Executors$RunnableAdapter.call() @bci=4 (Compiled frame)
 - java.util.concurrent.FutureTask.run() @bci=42 (Compiled frame)
 - java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask) @bci=1 (Compiled frame)
 - java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run() @bci=30 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5 (Interpreted frame)
 - java.lang.Thread.run() @bci=11 (Interpreted frame)

从我的角度来看,这个问题可能与Unsafe.defineAnonymousClass无法应对持续不断的电话java.lang.Thread.dumpThreads(反过来,需要实施java.lang.Thread.getStackTrace,在 JVM 内)。关键的一点是,由于final或包修饰符,我无法扩展此过程中涉及的任何核心类(例如Lookup, MethodHandleNatives等),以便引入一个锁,该锁会在调用时阻止棘手的不安全调用java.lang.Thread.dumpThreads仍在进行中。另外,我怀疑引入这样的锁也会大大减慢速度,因为 lambda 无处不在。

有人遇到过类似的问题吗?能帮忙解决一下吗?

谢谢你!


当然,在堆栈跟踪中也有类似的线程,我省略了它们,因为我认为它们与本例无关。

Thread 154: (state = BLOCKED) [Many of these....]
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.parkNanos(java.lang.Object, long) @bci=20 (Compiled frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(long) @bci=78 (Compiled frame)
 - org.eclipse.jetty.util.BlockingArrayQueue.poll(long, java.util.concurrent.TimeUnit) @bci=57, line=389 (Compiled frame)
 - org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll() @bci=12, line=516 (Compiled frame)
 - org.eclipse.jetty.util.thread.QueuedThreadPool.access$700(org.eclipse.jetty.util.thread.QueuedThreadPool) @bci=1, line=47 (Compiled frame)
 - org.eclipse.jetty.util.thread.QueuedThreadPool$3.run() @bci=300, line=575 (Compiled frame)
 - java.lang.Thread.run() @bci=11 (Compiled frame)


Thread 153: (state = BLOCKED) [and of these...]
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.ForkJoinPool.awaitWork(java.util.concurrent.ForkJoinPool$WorkQueue, int) @bci=354 (Compiled frame)
 - java.util.concurrent.ForkJoinPool.runWorker(java.util.concurrent.ForkJoinPool$WorkQueue) @bci=44 (Interpreted frame)
 - java.util.concurrent.ForkJoinWorkerThread.run() @bci=24 (Interpreted frame)


Thread 141: (state = BLOCKED) [and of these...]
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14 (Compiled frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await() @bci=42 (Compiled frame)
 - java.util.concurrent.LinkedBlockingQueue.take() @bci=29 (Compiled frame)
 - org.apache.tomcat.util.threads.TaskQueue.take() @bci=36, line=103 (Compiled frame)
 - org.apache.tomcat.util.threads.TaskQueue.take() @bci=1, line=31 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.getTask() @bci=149 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=26 (Interpreted frame)
 - java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5 (Interpreted frame)
 - org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run() @bci=4, line=61 (Interpreted frame)
 - java.lang.Thread.run() @bci=11 (Interpreted frame)

最后我设法解决了这个令人讨厌的问题。看来 JVM 可能会被类似发布的痕迹所困扰(至少涉及sun.misc.Unsafe.defineAnonymousClass)如果选项-XX:-类卸载 http://stas-blogspot.blogspot.it/2011/07/most-complete-list-of-xx-options-for.html#ClassUnloading被传递到 JVM 可执行文件(就像我试图修复的 JVM 的情况一样)。由于某种原因,这可能会在 Java 系统库中引发这种死锁式错误,该错误似乎是随机的(与所有死锁错误一样),并且随着 JVM 进程“老化”,这种可能性越来越大。再说一次,这对于死锁错误来说并不是什么新鲜事:放入机器中的“齿轮”(例如,应该被卸载但不是由于该选项而导致的类)越多,其中两个或多个启动的可能性就越大。

结果,删除该选项-XX:-ClassUnloading使这个问题完全消失。

底线是:永远不要使用-XX:-ClassUnloading在生产系统中(或者让任何人在 JVM 进程启动脚本中放置这样的选项),甚至在Java8,不应该受到PermGen的限制 https://dzone.com/articles/java-8-permgen-metaspace,但由于问题,它仍然会受到严重影响sun.misc.Unsafe.defineAnonymousClass .

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果一个线程调用 getStackTrace() 并且 lambda 定义(通过 Unsafe.defineAnonymousClass)发生在另一线程中,则 Java8 挂起 的相关文章

  • Qt中用于线程间通信的类设计

    问题陈述 用相机跟踪物体并相应地移动相机的方位角和仰角 Process 相机获取物体的图像 处理相机的每一帧以查找物体 应该被跟踪 并将每帧中生成的信息传递给机械设备 万向节 以平移和倾斜方式移动摄像机 Design 主 Gui 在一个线程
  • 具有阻塞功能的 Twisted LoopingCall

    我有一个应用程序需要轮询数据库以了解可能的配置更改 该应用程序是一个使用 Twisted 的简单 xmlrpc 服务器 我尝试过使用Twisted的LoopingCall来执行轮询 但是由于LoopingCall在主线程上运行 所以对db的
  • 如何使用 JPA 和 Hibernate 持久保存 OffsetTime 和 OffsetDateTime?

    我怎样才能坚持Java 8OffsetTime and OffsetDateTime使用 Hibernate 作为正确的 SQL 类型 TIME WITH TIMEZONE and TIMESTAMP WITH TIMEZONE 我找到了一
  • Shared_ptr 线程安全的开销是多少?

    std shared ptr保证是线程安全的 我不知道典型的实现使用什么机制来确保这一点 但肯定它必须有一些开销 即使您的应用程序是单线程的 这种开销也会存在 是上述情况吗 如果是这样 如果您不使用线程安全保证 这是否意味着它违反了 您不为
  • 原始类型是易失性的还是同步的?

    在 Java 中 如果变量的大小小于或等于 32 位 则赋值是原子的 但如果变量的大小大于 32 位 则赋值不是原子的 在双重或长分配的情况下 使用什么 易失性 同步 会更有效 Like volatile double x y 同步不适用于
  • 非阻塞方法中的饥饿

    一段时间以来 我一直在阅读有关非阻塞方法的内容 这是一段所谓的无锁计数器的代码 public class CasCounter private SimulatedCAS value public int getValue return va
  • BigDecimal#min 方法是否有资格作为 BinaryOperator?

    The Stream reduce方法需要一个BinaryOperator作为一个论点 a 的函数签名BinaryOperator is T T gt T The BigDecimal min方法的方法签名中只有 1 个参数 即 T gt
  • Kotlin 数据类中的函数作为参数会导致解析错误

    我有一个 Kotlin 帽子中的数据类正在使用 Parcelize注释以方便分割 问题是我现在想将一个函数传递给此类 但我真的不知道如何使该函数在打包过程中不被考虑 这是我的数据类 Parcelize data class GearCate
  • 在调用堆栈中看到大量 clr!CLR Semaphore::Wait

    我们看到很多像下面这样的调用堆栈 我可以知道什么条件 情况会发生这种情况吗 OS Thread Id 0x48654 559 Current frame ntdll NtWaitForSingleObject 0xa Child SP Re
  • iPhone 相当于 Application.DoEvents();

    iPHone 我们使用 MonoTouch 但 Obj C 答案还可以 我的单例域对象需要一段时间才能获取所有数据 因此它在线程中内部运行部分获取数据 我需要通知 UI 域已完成 目前我正在这样做 有没有更好的办法 在 WinForms 中
  • 如何在给定点停止线程?

    我试图停止一些线程 阅读一些有关优雅地执行此操作的正确方法的内容 但我一定做错了什么 因为它根本不起作用 起初我尝试不使用lock with IsRunning不稳定 然后尝试使用锁 这是我所拥有的 private volatile boo
  • iPhone 应用程序中的异步、同步、线程

    我正处于一个应用程序的设计阶段 该应用程序将利用 REST Web 服务 并且在使用异步 同步和线程方面遇到了困境 这是场景 假设您有三个选项可供深入研究 每个选项都有自己的基于 REST 的资源 我可以使用同步请求延迟加载每个请求 但这会
  • 在Spring中使用什么样的“EventBus”?内置、Reactor、Akka?

    我们将在几周后启动一个新的 Spring 4 应用程序 我们希望使用一些事件驱动的架构 今年 我到处读到有关 Reactor 的内容 在网上查找时 我偶然发现了 Akka 所以现在我们有3个选择 春天的ApplicationEvent ht
  • 避免在 AWS Lambda 上使用 netcore2.0 和 Serilog 进行两次日志记录

    将我的 netcore 项目升级到 2 0 后 当我的应用程序在使用 Serilog 框架的 AWS Lambda 上运行时 我会看到双日志 请参阅下面我的设置 public void ConfigureServices IServiceC
  • 我们可以使用 x86_64 CPU 原子在 PCI Express 上生成复合原子操作吗?

    如您所知 从2 0版本开始 PCI Express支持复合原子操作 FetchAdd Swap CAS https pcisig com sites default files specification documents ECN Ato
  • 输出字段值相同的记录

    该主题可能会重复 我在不同的场景下询问这个话题 https stackoverflow com questions 64150691 select records which the values of the field are the
  • 使用 async/await 抛出和捕获异常的正确方法

    全部请拿下面的二维码 Task
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur

随机推荐