001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018    
019    import java.io.InputStream;
020    
021    import java.lang.management.ManagementFactory;
022    import java.lang.management.RuntimeMXBean;
023    
024    import java.util.Date;
025    import java.util.Map;
026    
027    /**
028     * @author Tina Tian
029     * @author Shuyang Zhou
030     */
031    public class ThreadUtil {
032    
033            public static Thread[] getThreads() {
034                    Thread currentThread = Thread.currentThread();
035    
036                    ThreadGroup threadGroup = currentThread.getThreadGroup();
037    
038                    while (threadGroup.getParent() != null) {
039                            threadGroup = threadGroup.getParent();
040                    }
041    
042                    int threadCountGuess = threadGroup.activeCount();
043    
044                    Thread[] threads = new Thread[threadCountGuess];
045    
046                    int threadCountActual = threadGroup.enumerate(threads);
047    
048                    while (threadCountActual == threadCountGuess) {
049                            threadCountGuess *= 2;
050    
051                            threads = new Thread[threadCountGuess];
052    
053                            threadCountActual = threadGroup.enumerate(threads);
054                    }
055    
056                    return threads;
057            }
058    
059            public static String threadDump() {
060    
061                    String threadDump = _getThreadDumpFromJstack();
062    
063                    if (Validator.isNull(threadDump)) {
064                            threadDump = _getThreadDumpFromStackTrace();
065                    }
066    
067                    return "\n\n".concat(threadDump);
068            }
069    
070            private static String _getThreadDumpFromJstack() {
071                    UnsyncByteArrayOutputStream outputStream =
072                            new UnsyncByteArrayOutputStream();
073    
074                    try {
075                            String vendorURL = System.getProperty("java.vendor.url");
076    
077                            if (!vendorURL.equals("http://java.oracle.com/") &&
078                                    !vendorURL.equals("http://java.sun.com/")) {
079    
080                                    return StringPool.BLANK;
081                            }
082    
083                            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
084    
085                            String name = runtimeMXBean.getName();
086    
087                            if (Validator.isNull(name)) {
088                                    return StringPool.BLANK;
089                            }
090    
091                            int pos = name.indexOf(CharPool.AT);
092    
093                            if (pos == -1) {
094                                    return StringPool.BLANK;
095                            }
096    
097                            String pidString = name.substring(0, pos);
098    
099                            if (!Validator.isNumber(pidString)) {
100                                    return StringPool.BLANK;
101                            }
102    
103                            Runtime runtime = Runtime.getRuntime();
104    
105                            int pid = GetterUtil.getInteger(pidString);
106    
107                            String[] cmd = new String[] {"jstack", String.valueOf(pid)};
108    
109                            Process process = runtime.exec(cmd);
110    
111                            InputStream inputStream = process.getInputStream();
112    
113                            StreamUtil.transfer(inputStream, outputStream);
114                    }
115                    catch (Exception e) {
116                    }
117    
118                    return outputStream.toString();
119            }
120    
121            private static String _getThreadDumpFromStackTrace() {
122                    String jvm =
123                            System.getProperty("java.vm.name") + " " +
124                                    System.getProperty("java.vm.version");
125    
126                    StringBundler sb = new StringBundler(
127                            "Full thread dump of " + jvm + " on " + String.valueOf(new Date()) +
128                                    "\n\n");
129    
130                    Map<Thread, StackTraceElement[]> stackTraces =
131                            Thread.getAllStackTraces();
132    
133                    for (Map.Entry<Thread, StackTraceElement[]> entry :
134                                    stackTraces.entrySet()) {
135    
136                            Thread thread = entry.getKey();
137                            StackTraceElement[] elements = entry.getValue();
138    
139                            sb.append(StringPool.QUOTE);
140                            sb.append(thread.getName());
141                            sb.append(StringPool.QUOTE);
142    
143                            if (thread.getThreadGroup() != null) {
144                                    sb.append(StringPool.SPACE);
145                                    sb.append(StringPool.OPEN_PARENTHESIS);
146                                    sb.append(thread.getThreadGroup().getName());
147                                    sb.append(StringPool.CLOSE_PARENTHESIS);
148                            }
149    
150                            sb.append(", priority=");
151                            sb.append(thread.getPriority());
152                            sb.append(", id=");
153                            sb.append(thread.getId());
154                            sb.append(", state=");
155                            sb.append(thread.getState());
156                            sb.append("\n");
157    
158                            for (int i = 0; i < elements.length; i++) {
159                                    sb.append("\t");
160                                    sb.append(elements[i]);
161                                    sb.append("\n");
162                            }
163    
164                            sb.append("\n");
165                    }
166    
167                    return sb.toString();
168            }
169    
170    }