java - RUNNABLE 线程 - 它移动了吗?

标签 java glassfish-3 jstack

我正在调查在 Java 7 上运行的 Glassfish 3.1.2.2 托管应用程序遇到的高 CPU 使用率问题

CPU 使用率将开始从“正常”水平上升,在 20 分钟内从 5-10% 左右上升到 100%,然后保持在 90-100 之间并且不会下降,重新启动应用程序即可恢复正常。

下面的 2 段摘录取自 2 个线程转储,每个线程转储的时间间隔为 10 分钟。

使用 VisualVM CPU Profiler 快照交叉引用整个转储显示,大约有 10 个线程在执行该代码区域,这些线程似乎将整个时间都花在了下面所示的方法中。

除了锁定的对象引用之外,所有 10 个线程的两个线程转储中的整个堆栈(很大并在下面缩写)都是相同的。

我想知道这里发生了什么。包括为什么锁定的对象引用发生了变化?

代码是否陷入循环或某处有锁?

线程转储1

"http-thread-pool-8080(3)" - Thread t@112
   java.lang.Thread.State: RUNNABLE
    at java.lang.Throwable.fillInStackTrace(Native Method)
    at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
    - locked <2328e584> (a java.lang.InterruptedException)
    at java.lang.Throwable.<init>(Throwable.java:250)
    at java.lang.Exception.<init>(Exception.java:54)
    at java.lang.InterruptedException.<init>(InterruptedException.java:57)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1325)
    at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.tryLock(ReentrantReadWriteLock.java:873)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.acquireLock(POAImpl.java:390)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.readLock(POAImpl.java:422)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.enter(POAImpl.java:1743)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.getServantWithPI(CorbaServerRequestDispatcherImpl.java:302)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:196)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
    at com.sun.corba.ee.impl.protocol.SharedCDRClientRequestDispatcherImpl.marshalingComplete(SharedCDRClientRequestDispatcherImpl.java:126)
    at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.invoke(CorbaClientDelegateImpl.java:273)
    at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClientDelegateImpl.java:395)
    at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:130)
...

线程转储2

"http-thread-pool-8080(3)" - Thread t@112
   java.lang.Thread.State: RUNNABLE
    at java.lang.Throwable.fillInStackTrace(Native Method)
    at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
    - locked <83c9c3a> (a java.lang.InterruptedException)
    at java.lang.Throwable.<init>(Throwable.java:250)
    at java.lang.Exception.<init>(Exception.java:54)
    at java.lang.InterruptedException.<init>(InterruptedException.java:57)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1325)
    at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.tryLock(ReentrantReadWriteLock.java:873)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.acquireLock(POAImpl.java:390)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.readLock(POAImpl.java:422)
    at com.sun.corba.ee.impl.oa.poa.POAImpl.enter(POAImpl.java:1743)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.getServantWithPI(CorbaServerRequestDispatcherImpl.java:302)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:196)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
    at com.sun.corba.ee.impl.protocol.SharedCDRClientRequestDispatcherImpl.marshalingComplete(SharedCDRClientRequestDispatcherImpl.java:126)
    at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.invoke(CorbaClientDelegateImpl.java:273)
    at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClientDelegateImpl.java:395)
    at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:130)
...

更新

这是可能导致问题的 POAImpl acquireLock 方法...

private void acquireLock(Lock lock) {
        MethodMonitor __$mm$__ = (MethodMonitor)__$mm$__0.content();
        if (__$mm$__ != null) {
            __$mm$__.enter(1, new Object[]{lock});
        }

        try {
            long timeout = 1L;
            boolean locked = false;
            boolean interrupted = false;
            int count = 0;
            int reportingThreshhold = 1;

            while(!locked) {
                if (count >= reportingThreshhold) {
                    this.acquireLockWaiting(count, __$mm$__, 1);
                    if (reportingThreshhold < 1073741823) {
                        reportingThreshhold *= 2;
                    }
                }

                try {
                    locked = lock.tryLock(1L, TimeUnit.SECONDS);
                    ++count;
                } catch (InterruptedException var13) {
                    interrupted = true;
                }

                if (interrupted) {
                    Thread.currentThread().interrupt();
                }
            }

            if (__$mm$__ != null) {
                __$mm$__.exit(1);
            }

        } finally {
            if (__$mm$__ != null) {
                __$mm$__.exit(1);
            }

        }
    }

最佳答案

至于提供的代码。它本质上是做这样的事情:

public static void main(String[] args) throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    Thread t=new Thread(()->lock.lock()); //lets simulate that Lock is locked
    t.start();
    t.join();
    int times = 0;
    Thread.currentThread().interrupt(); //and for whatever reasons - thread was interrupted from outside
    boolean locked=false;
    while (!locked) {
        try {
            boolean gotLock=lock.tryLock(1, TimeUnit.SECONDS);
            System.out.println("Got lock?: "+gotLock);
        } catch (InterruptedException e) {
            System.out.println("Thrown times:" + times++);
            Thread.currentThread().interrupt(); // iterrupts again - will throw on getLock no matter what now
        }
    }
}

所以基本上有一次中断 - 你将陷入无限循环的边缘 - 没有延迟 - 这会占用 CPU。我建议围绕该中断处理添加诊断日志记录,以查看发生了什么。

关于java - RUNNABLE 线程 - 它移动了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57203090/

相关文章:

java - Maven 花费大量时间运行集成测试

java - 用于生成和使用 JSON 的 Controller 的 Spring RequestMapping

带有特殊字符的 Java SQL 表名

java - Firebase 数据库监听器返回空值

java - 在没有 web.xml 的 Jersey 中使用 ContainerRequestFilter

java - 为什么当/tmp/.java_pid<num>套接字文件被删除时jstack不工作

java - jstack 输出 - 获取 java Thread.getId 的 tid

hibernate - JPA。从 Hibernate 迁移到 Eclipselink 时的事务问题

java - 以与 NetBeans 相同的方式运行 GlassFish 3.1.1

java - VisualVM 线程转储与堆转储不匹配?