001    /**
002     * Copyright (c) 2000-2013 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                    String threadDump = _getThreadDumpFromJstack();
061    
062                    if (Validator.isNull(threadDump)) {
063                            threadDump = _getThreadDumpFromStackTrace();
064                    }
065    
066                    return "\n\n".concat(threadDump);
067            }
068    
069            private static String _getThreadDumpFromJstack() {
070                    UnsyncByteArrayOutputStream outputStream =
071                            new UnsyncByteArrayOutputStream();
072    
073                    try {
074                            String vendorURL = System.getProperty("java.vendor.url");
075    
076                            if (!vendorURL.equals("http://java.oracle.com/") &&
077                                    !vendorURL.equals("http://java.sun.com/")) {
078    
079                                    return StringPool.BLANK;
080                            }
081    
082                            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
083    
084                            String name = runtimeMXBean.getName();
085    
086                            if (Validator.isNull(name)) {
087                                    return StringPool.BLANK;
088                            }
089    
090                            int pos = name.indexOf(CharPool.AT);
091    
092                            if (pos == -1) {
093                                    return StringPool.BLANK;
094                            }
095    
096                            String pidString = name.substring(0, pos);
097    
098                            if (!Validator.isNumber(pidString)) {
099                                    return StringPool.BLANK;
100                            }
101    
102                            Runtime runtime = Runtime.getRuntime();
103    
104                            int pid = GetterUtil.getInteger(pidString);
105    
106                            String[] cmd = new String[] {"jstack", String.valueOf(pid)};
107    
108                            Process process = runtime.exec(cmd);
109    
110                            InputStream inputStream = process.getInputStream();
111    
112                            StreamUtil.transfer(inputStream, outputStream);
113                    }
114                    catch (Exception e) {
115                    }
116    
117                    return outputStream.toString();
118            }
119    
120            private static String _getThreadDumpFromStackTrace() {
121                    String jvm =
122                            System.getProperty("java.vm.name") + " " +
123                                    System.getProperty("java.vm.version");
124    
125                    StringBundler sb = new StringBundler(
126                            "Full thread dump of " + jvm + " on " + String.valueOf(new Date()) +
127                                    "\n\n");
128    
129                    Map<Thread, StackTraceElement[]> stackTraces =
130                            Thread.getAllStackTraces();
131    
132                    for (Map.Entry<Thread, StackTraceElement[]> entry :
133                                    stackTraces.entrySet()) {
134    
135                            Thread thread = entry.getKey();
136                            StackTraceElement[] elements = entry.getValue();
137    
138                            sb.append(StringPool.QUOTE);
139                            sb.append(thread.getName());
140                            sb.append(StringPool.QUOTE);
141    
142                            if (thread.getThreadGroup() != null) {
143                                    sb.append(StringPool.SPACE);
144                                    sb.append(StringPool.OPEN_PARENTHESIS);
145                                    sb.append(thread.getThreadGroup().getName());
146                                    sb.append(StringPool.CLOSE_PARENTHESIS);
147                            }
148    
149                            sb.append(", priority=");
150                            sb.append(thread.getPriority());
151                            sb.append(", id=");
152                            sb.append(thread.getId());
153                            sb.append(", state=");
154                            sb.append(thread.getState());
155                            sb.append("\n");
156    
157                            for (int i = 0; i < elements.length; i++) {
158                                    sb.append("\t");
159                                    sb.append(elements[i]);
160                                    sb.append("\n");
161                            }
162    
163                            sb.append("\n");
164                    }
165    
166                    return sb.toString();
167            }
168    
169    }