Search in sources :

Example 71 with ThreadInfo

use of java.lang.management.ThreadInfo in project elasticsearch by elastic.

the class HotThreads method innerDetect.

private String innerDetect() throws Exception {
    ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
    if (threadBean.isThreadCpuTimeSupported() == false) {
        throw new ElasticsearchException("thread CPU time is not supported on this JDK");
    }
    StringBuilder sb = new StringBuilder();
    sb.append("Hot threads at ");
    sb.append(DATE_TIME_FORMATTER.printer().print(System.currentTimeMillis()));
    sb.append(", interval=");
    sb.append(interval);
    sb.append(", busiestThreads=");
    sb.append(busiestThreads);
    sb.append(", ignoreIdleThreads=");
    sb.append(ignoreIdleThreads);
    sb.append(":\n");
    Map<Long, MyThreadInfo> threadInfos = new HashMap<>();
    for (long threadId : threadBean.getAllThreadIds()) {
        // ignore our own thread...
        if (Thread.currentThread().getId() == threadId) {
            continue;
        }
        long cpu = threadBean.getThreadCpuTime(threadId);
        if (cpu == -1) {
            continue;
        }
        ThreadInfo info = threadBean.getThreadInfo(threadId, 0);
        if (info == null) {
            continue;
        }
        threadInfos.put(threadId, new MyThreadInfo(cpu, info));
    }
    Thread.sleep(interval.millis());
    for (long threadId : threadBean.getAllThreadIds()) {
        // ignore our own thread...
        if (Thread.currentThread().getId() == threadId) {
            continue;
        }
        long cpu = threadBean.getThreadCpuTime(threadId);
        if (cpu == -1) {
            threadInfos.remove(threadId);
            continue;
        }
        ThreadInfo info = threadBean.getThreadInfo(threadId, 0);
        if (info == null) {
            threadInfos.remove(threadId);
            continue;
        }
        MyThreadInfo data = threadInfos.get(threadId);
        if (data != null) {
            data.setDelta(cpu, info);
        } else {
            threadInfos.remove(threadId);
        }
    }
    // sort by delta CPU time on thread.
    List<MyThreadInfo> hotties = new ArrayList<>(threadInfos.values());
    final int busiestThreads = Math.min(this.busiestThreads, hotties.size());
    // skip that for now
    CollectionUtil.introSort(hotties, new Comparator<MyThreadInfo>() {

        @Override
        public int compare(MyThreadInfo o1, MyThreadInfo o2) {
            if ("cpu".equals(type)) {
                return (int) (o2.cpuTime - o1.cpuTime);
            } else if ("wait".equals(type)) {
                return (int) (o2.waitedTime - o1.waitedTime);
            } else if ("block".equals(type)) {
                return (int) (o2.blockedTime - o1.blockedTime);
            }
            throw new IllegalArgumentException("expected thread type to be either 'cpu', 'wait', or 'block', but was " + type);
        }
    });
    // analyse N stack traces for M busiest threads
    long[] ids = new long[busiestThreads];
    for (int i = 0; i < busiestThreads; i++) {
        MyThreadInfo info = hotties.get(i);
        ids[i] = info.info.getThreadId();
    }
    ThreadInfo[][] allInfos = new ThreadInfo[threadElementsSnapshotCount][];
    for (int j = 0; j < threadElementsSnapshotCount; j++) {
        // NOTE, javadoc of getThreadInfo says: If a thread of the given ID is not alive or does not exist,
        // null will be set in the corresponding element in the returned array. A thread is alive if it has
        // been started and has not yet died.
        allInfos[j] = threadBean.getThreadInfo(ids, Integer.MAX_VALUE);
        Thread.sleep(threadElementsSnapshotDelay.millis());
    }
    for (int t = 0; t < busiestThreads; t++) {
        long time = 0;
        if ("cpu".equals(type)) {
            time = hotties.get(t).cpuTime;
        } else if ("wait".equals(type)) {
            time = hotties.get(t).waitedTime;
        } else if ("block".equals(type)) {
            time = hotties.get(t).blockedTime;
        }
        String threadName = null;
        for (ThreadInfo[] info : allInfos) {
            if (info != null && info[t] != null) {
                if (ignoreIdleThreads && isIdleThread(info[t])) {
                    info[t] = null;
                    continue;
                }
                threadName = info[t].getThreadName();
                break;
            }
        }
        if (threadName == null) {
            // thread is not alive yet or died before the first snapshot - ignore it!
            continue;
        }
        double percent = (((double) time) / interval.nanos()) * 100;
        sb.append(String.format(Locale.ROOT, "%n%4.1f%% (%s out of %s) %s usage by thread '%s'%n", percent, TimeValue.timeValueNanos(time), interval, type, threadName));
        // for each snapshot (2nd array index) find later snapshot for same thread with max number of
        // identical StackTraceElements (starting from end of each)
        boolean[] done = new boolean[threadElementsSnapshotCount];
        for (int i = 0; i < threadElementsSnapshotCount; i++) {
            if (done[i])
                continue;
            int maxSim = 1;
            boolean[] similars = new boolean[threadElementsSnapshotCount];
            for (int j = i + 1; j < threadElementsSnapshotCount; j++) {
                if (done[j])
                    continue;
                int similarity = similarity(allInfos[i][t], allInfos[j][t]);
                if (similarity > maxSim) {
                    maxSim = similarity;
                    similars = new boolean[threadElementsSnapshotCount];
                }
                if (similarity == maxSim)
                    similars[j] = true;
            }
            // print out trace maxSim levels of i, and mark similar ones as done
            int count = 1;
            for (int j = i + 1; j < threadElementsSnapshotCount; j++) {
                if (similars[j]) {
                    done[j] = true;
                    count++;
                }
            }
            if (allInfos[i][t] != null) {
                final StackTraceElement[] show = allInfos[i][t].getStackTrace();
                if (count == 1) {
                    sb.append(String.format(Locale.ROOT, "  unique snapshot%n"));
                    for (int l = 0; l < show.length; l++) {
                        sb.append(String.format(Locale.ROOT, "    %s%n", show[l]));
                    }
                } else {
                    sb.append(String.format(Locale.ROOT, "  %d/%d snapshots sharing following %d elements%n", count, threadElementsSnapshotCount, maxSim));
                    for (int l = show.length - maxSim; l < show.length; l++) {
                        sb.append(String.format(Locale.ROOT, "    %s%n", show[l]));
                    }
                }
            }
        }
    }
    return sb.toString();
}
Also used : ThreadMXBean(java.lang.management.ThreadMXBean) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ElasticsearchException(org.elasticsearch.ElasticsearchException) ThreadInfo(java.lang.management.ThreadInfo)

Example 72 with ThreadInfo

use of java.lang.management.ThreadInfo in project jetty.project by eclipse.

the class JavaMonitorTools method stacktraces.

private String stacktraces(final ThreadInfo[] threads, final int i) {
    if (i >= threads.length) {
        return "";
    }
    final ThreadInfo thread = threads[i];
    final StringBuilder trace = new StringBuilder();
    for (int stack_i = 0; stack_i < Math.min(thread.getStackTrace().length, MAX_STACK); stack_i++) {
        if (stack_i == (MAX_STACK - 1)) {
            trace.append("    ...");
        } else {
            trace.append("    at ").append(thread.getStackTrace()[stack_i]).append("\n");
        }
    }
    return "\"" + thread.getThreadName() + "\", id " + thread.getThreadId() + " is " + thread.getThreadState() + " on " + thread.getLockName() + ", owned by " + thread.getLockOwnerName() + ", id " + thread.getLockOwnerId() + "\n" + trace + "\n\n" + stacktraces(threads, i + 1);
}
Also used : ThreadInfo(java.lang.management.ThreadInfo)

Example 73 with ThreadInfo

use of java.lang.management.ThreadInfo in project elasticsearch by elastic.

the class LongGCDisruption method startDisrupting.

@Override
public synchronized void startDisrupting() {
    if (suspendedThreads == null) {
        boolean success = false;
        try {
            suspendedThreads = ConcurrentHashMap.newKeySet();
            final String currentThreadName = Thread.currentThread().getName();
            assert isDisruptedNodeThread(currentThreadName) == false : "current thread match pattern. thread name: " + currentThreadName + ", node: " + disruptedNode;
            // we spawn a background thread to protect against deadlock which can happen
            // if there are shared resources between caller thread and and suspended threads
            // see unsafeClasses to how to avoid that
            final AtomicReference<Exception> stoppingError = new AtomicReference<>();
            final Thread stoppingThread = new Thread(new AbstractRunnable() {

                @Override
                public void onFailure(Exception e) {
                    stoppingError.set(e);
                }

                @Override
                protected void doRun() throws Exception {
                    // keep trying to stop threads, until no new threads are discovered.
                    while (stopNodeThreads(suspendedThreads)) {
                        if (Thread.interrupted()) {
                            return;
                        }
                    }
                }
            });
            stoppingThread.setName(currentThreadName + "[LongGCDisruption][threadStopper]");
            stoppingThread.start();
            try {
                stoppingThread.join(getStoppingTimeoutInMillis());
            } catch (InterruptedException e) {
                // best effort to signal stopping
                stoppingThread.interrupt();
                throw new RuntimeException(e);
            }
            if (stoppingError.get() != null) {
                throw new RuntimeException("unknown error while stopping threads", stoppingError.get());
            }
            if (stoppingThread.isAlive()) {
                logger.warn("failed to stop node [{}]'s threads within [{}] millis. Stopping thread stack trace:\n {}", disruptedNode, getStoppingTimeoutInMillis(), stackTrace(stoppingThread.getStackTrace()));
                // best effort;
                stoppingThread.interrupt();
                throw new RuntimeException("stopping node threads took too long");
            }
            // of the threads that was suspended
            if (isBlockDetectionSupported()) {
                blockDetectionThread = new Thread(new AbstractRunnable() {

                    @Override
                    public void onFailure(Exception e) {
                        if (e instanceof InterruptedException == false) {
                            throw new AssertionError("unexpected exception in blockDetectionThread", e);
                        }
                    }

                    @Override
                    protected void doRun() throws Exception {
                        while (Thread.currentThread().isInterrupted() == false) {
                            ThreadInfo[] threadInfos = threadBean.dumpAllThreads(true, true);
                            for (ThreadInfo threadInfo : threadInfos) {
                                if (isDisruptedNodeThread(threadInfo.getThreadName()) == false && threadInfo.getLockOwnerName() != null && isDisruptedNodeThread(threadInfo.getLockOwnerName())) {
                                    // find ThreadInfo object of the blocking thread (if available)
                                    ThreadInfo blockingThreadInfo = null;
                                    for (ThreadInfo otherThreadInfo : threadInfos) {
                                        if (otherThreadInfo.getThreadId() == threadInfo.getLockOwnerId()) {
                                            blockingThreadInfo = otherThreadInfo;
                                            break;
                                        }
                                    }
                                    onBlockDetected(threadInfo, blockingThreadInfo);
                                }
                            }
                            Thread.sleep(getBlockDetectionIntervalInMillis());
                        }
                    }
                });
                blockDetectionThread.setName(currentThreadName + "[LongGCDisruption][blockDetection]");
                blockDetectionThread.start();
            }
            success = true;
        } finally {
            if (success == false) {
                stopBlockDetection();
                // resume threads if failed
                resumeThreads(suspendedThreads);
                suspendedThreads = null;
            }
        }
    } else {
        throw new IllegalStateException("can't disrupt twice, call stopDisrupting() first");
    }
}
Also used : AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) AtomicReference(java.util.concurrent.atomic.AtomicReference) ThreadInfo(java.lang.management.ThreadInfo)

Example 74 with ThreadInfo

use of java.lang.management.ThreadInfo in project elasticsearch by elastic.

the class LongGCDisruptionTest method testBlockDetection.

public void testBlockDetection() throws Exception {
    final String disruptedNodeName = "disrupted_node";
    final String blockedNodeName = "blocked_node";
    CountDownLatch waitForBlockDetectionResult = new CountDownLatch(1);
    AtomicReference<ThreadInfo> blockDetectionResult = new AtomicReference<>();
    LongGCDisruption disruption = new LongGCDisruption(random(), disruptedNodeName) {

        @Override
        protected Pattern[] getUnsafeClasses() {
            return new Pattern[0];
        }

        @Override
        protected void onBlockDetected(ThreadInfo blockedThread, @Nullable ThreadInfo blockingThread) {
            blockDetectionResult.set(blockedThread);
            waitForBlockDetectionResult.countDown();
        }

        @Override
        protected long getBlockDetectionIntervalInMillis() {
            return 10L;
        }
    };
    if (disruption.isBlockDetectionSupported() == false) {
        return;
    }
    final AtomicBoolean stop = new AtomicBoolean();
    final CountDownLatch underLock = new CountDownLatch(1);
    final CountDownLatch pauseUnderLock = new CountDownLatch(1);
    final LockedExecutor lockedExecutor = new LockedExecutor();
    final AtomicLong ops = new AtomicLong();
    try {
        for (int i = 0; i < 5; i++) {
            // at least one locked and one none lock thread
            final boolean lockedExec = (i < 4 && randomBoolean()) || i == 0;
            Thread thread = new Thread(() -> {
                while (stop.get() == false) {
                    if (lockedExec) {
                        lockedExecutor.executeLocked(() -> {
                            try {
                                underLock.countDown();
                                ops.incrementAndGet();
                                pauseUnderLock.await();
                            } catch (InterruptedException e) {
                            }
                        });
                    } else {
                        ops.incrementAndGet();
                    }
                }
            });
            thread.setName("[" + disruptedNodeName + "][" + i + "]");
            thread.start();
        }
        for (int i = 0; i < 5; i++) {
            // at least one locked and one none lock thread
            final boolean lockedExec = (i < 4 && randomBoolean()) || i == 0;
            Thread thread = new Thread(() -> {
                while (stop.get() == false) {
                    if (lockedExec) {
                        lockedExecutor.executeLocked(() -> {
                            ops.incrementAndGet();
                        });
                    } else {
                        ops.incrementAndGet();
                    }
                }
            });
            thread.setName("[" + blockedNodeName + "][" + i + "]");
            thread.start();
        }
        // make sure some threads of test_node are under lock
        underLock.await();
        disruption.startDisrupting();
        waitForBlockDetectionResult.await(30, TimeUnit.SECONDS);
        disruption.stopDisrupting();
        ThreadInfo threadInfo = blockDetectionResult.get();
        assertNotNull(threadInfo);
        assertThat(threadInfo.getThreadName(), containsString("[" + blockedNodeName + "]"));
        assertThat(threadInfo.getLockOwnerName(), containsString("[" + disruptedNodeName + "]"));
        assertThat(threadInfo.getLockInfo().getClassName(), containsString(ReentrantLock.class.getName()));
    } finally {
        stop.set(true);
        pauseUnderLock.countDown();
    }
}
Also used : Pattern(java.util.regex.Pattern) AtomicReference(java.util.concurrent.atomic.AtomicReference) Matchers.containsString(org.hamcrest.Matchers.containsString) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicLong(java.util.concurrent.atomic.AtomicLong) ThreadInfo(java.lang.management.ThreadInfo) Nullable(org.elasticsearch.common.Nullable)

Example 75 with ThreadInfo

use of java.lang.management.ThreadInfo in project zoj by licheng.

the class Sandbox method main.

public static void main(String[] args) {
    if (args.length != 6) {
        logError("Invalid args length: " + args.length);
        halt(JudgeReply.JUDGE_INTERNAL_ERROR);
    }
    GregorianCalendar gc = new GregorianCalendar();
    try {
        // The purpose of Scaner here is to preload this class so that the target class can use it directly.
        Scanner scanner = new Scanner(args[0]);
        port = scanner.nextInt();
        timeLimit = Integer.parseInt(args[1]);
        memoryLimit = Integer.parseInt(args[2]);
        outputLimit = Integer.parseInt(args[3]);
        uid = Integer.parseInt(args[4]);
        gid = Integer.parseInt(args[5]);
        socket = new Socket("127.0.0.1", port);
        out = new DataOutputStream(socket.getOutputStream());
        System.setIn(new BufferedInputStream(new FileInputStream("input")));
        System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("p.out") {

            public void write(int b) throws IOException {
                try {
                    super.write(b);
                } catch (IOException e) {
                    if (e.getMessage().equals("File too large")) {
                        SandboxSecurityManager.targetThread = null;
                        halt(JudgeReply.OUTPUT_LIMIT_EXCEEDED);
                    }
                    throw e;
                }
            }

            public void write(byte[] b, int off, int len) throws IOException {
                try {
                    super.write(b, off, len);
                } catch (IOException e) {
                    if (e.getMessage().equals("File too large")) {
                        SandboxSecurityManager.targetThread = null;
                        halt(JudgeReply.OUTPUT_LIMIT_EXCEEDED);
                    }
                    throw e;
                }
            }
        })));
        System.setErr(new PrintStream(new BufferedOutputStream(new FileOutputStream("/dev/null"))));
    } catch (Exception e) {
        logError(printError(e));
        halt(JudgeReply.JUDGE_INTERNAL_ERROR);
        return;
    }
    System.gc();
    baseHeapMemoryConsumption = memoryBean.getHeapMemoryUsage().getUsed();
    targetThread.start();
    for (; ; ) {
        Thread.State state;
        ThreadInfo info = threadBean.getThreadInfo(targetThread.getId());
        if (info == null) {
            state = Thread.State.TERMINATED;
        } else {
            state = info.getThreadState();
        }
        if (state == Thread.State.RUNNABLE || state == Thread.State.NEW || state == Thread.State.TERMINATED) {
            updateConsumptions();
            try {
                sendRunningMessage(timeConsumption, memoryConsumption);
            } catch (IOException e) {
                halt(JudgeReply.JUDGE_INTERNAL_ERROR);
            }
            if (state == Thread.State.TERMINATED) {
                break;
            }
        } else if (SandboxSecurityManager.targetThread != null) {
            logError("Invalid thread state " + state);
            halt(JudgeReply.RUNTIME_ERROR);
        }
        try {
            targetThread.join(UPDATE_TIME_THRESHOLD);
        } catch (InterruptedException e) {
            Runtime.getRuntime().halt(0);
            break;
        }
    }
    closeSocket();
}
Also used : Scanner(java.util.Scanner) PrintStream(java.io.PrintStream) DataOutputStream(java.io.DataOutputStream) GregorianCalendar(java.util.GregorianCalendar) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ThreadInfo(java.lang.management.ThreadInfo) BufferedInputStream(java.io.BufferedInputStream) FileOutputStream(java.io.FileOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) Socket(java.net.Socket)

Aggregations

ThreadInfo (java.lang.management.ThreadInfo)124 ThreadMXBean (java.lang.management.ThreadMXBean)56 HashMap (java.util.HashMap)10 IOException (java.io.IOException)8 ArrayList (java.util.ArrayList)8 HashSet (java.util.HashSet)7 Map (java.util.Map)7 LockInfo (java.lang.management.LockInfo)6 MonitorInfo (java.lang.management.MonitorInfo)6 Test (org.junit.Test)5 Date (java.util.Date)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 FileOutputStream (java.io.FileOutputStream)3 PrintStream (java.io.PrintStream)3 PrintWriter (java.io.PrintWriter)3 Method (java.lang.reflect.Method)3 LinkedHashSet (java.util.LinkedHashSet)3 TreeMap (java.util.TreeMap)3 ExecutorService (java.util.concurrent.ExecutorService)3 HealthCheckResultEntry (fish.payara.notification.healthcheck.HealthCheckResultEntry)2