You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
5.3 KiB
147 lines
5.3 KiB
package com.fr.design.carton; |
|
|
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.stable.ArrayUtils; |
|
import com.fr.stable.StableUtils; |
|
import com.fr.stable.StringUtils; |
|
import org.jetbrains.annotations.NotNull; |
|
|
|
import java.io.BufferedWriter; |
|
import java.io.File; |
|
import java.io.FileWriter; |
|
import java.io.IOException; |
|
import java.lang.management.ManagementFactory; |
|
import java.lang.management.ThreadInfo; |
|
import java.lang.management.ThreadMXBean; |
|
import java.text.SimpleDateFormat; |
|
|
|
import static com.fr.design.carton.CartonConstants.EASY_CHECKER_FILE_NAME; |
|
import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH; |
|
import static com.fr.design.carton.CartonConstants.TIMER_CHECKER_FILE_NAME; |
|
|
|
/** |
|
* 设计器卡顿业务工具类 |
|
* |
|
* @author Levy.Xie |
|
* @since 11.0 |
|
* Created on 2024/07/10 |
|
*/ |
|
public class CartonUtils { |
|
|
|
/** |
|
* 堆栈元素输出为文本 |
|
* |
|
* @param stackTrace 堆栈元素 |
|
* @return 文本 |
|
*/ |
|
public static String stackTraceToString(StackTraceElement[] stackTrace) { |
|
StringBuilder result = new StringBuilder(); |
|
for (StackTraceElement stackTraceElement : stackTrace) { |
|
String indentation = " "; |
|
result.append("~").append(indentation).append(stackTraceElement); |
|
} |
|
return result.toString(); |
|
} |
|
|
|
/** |
|
* 命令行显示堆栈信息 |
|
* |
|
* @param stackTrace 堆栈元素 |
|
* @return 文本 |
|
*/ |
|
public static String stackTraceToStringForConsole(StackTraceElement[] stackTrace) { |
|
StringBuilder result = new StringBuilder(); |
|
for (StackTraceElement stackTraceElement : stackTrace) { |
|
String indentation = " "; |
|
result.append("\r\n").append(indentation).append(stackTraceElement); |
|
} |
|
return result.toString(); |
|
} |
|
|
|
/** |
|
* 堆栈是否一致 |
|
* |
|
* @param a 堆栈A |
|
* @param b 堆栈B |
|
* @return 是否一致 |
|
*/ |
|
public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) { |
|
if (!ArrayUtils.isSameLength(a, b)) { |
|
return false; |
|
} |
|
for (int i = 0; i < a.length; ++i) { |
|
if (!a[i].equals(b[i])) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* 检查死锁 |
|
*/ |
|
public static void checkForDeadlock() { |
|
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); |
|
long[] threadIds = threadBean.findDeadlockedThreads(); |
|
if (threadIds == null) { |
|
return; |
|
} |
|
FineLoggerFactory.getLogger().warn("deadlock detected involving the following threads:"); |
|
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE); |
|
for (ThreadInfo info : threadInfos) { |
|
FineLoggerFactory.getLogger().warn("Thread # {} {} ( {} ) waiting on {} held by {} {}", info.getThreadId(), info.getThreadName(), |
|
info.getThreadState(), info.getLockName(), info.getLockOwnerName(), CartonUtils.stackTraceToStringForConsole(info.getStackTrace())); |
|
} |
|
} |
|
|
|
/** |
|
* 输出卡顿日志 |
|
* |
|
* @param message 文本信息 |
|
* @param flag 类型,true时为简单检查、false时为定时检查 |
|
*/ |
|
public static void outPutJournalLog(String message, int flag) { |
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); |
|
String date = simpleDateFormat.format(System.currentTimeMillis()); |
|
String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? EASY_CHECKER_FILE_NAME : TIMER_CHECKER_FILE_NAME; |
|
String[] split = date.split("-"); |
|
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); |
|
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); |
|
File dirFile = new File(dirPath); |
|
File file = new File(StableUtils.pathJoin(dirPath, filename)); |
|
try { |
|
if (!file.exists()) { |
|
if (!dirFile.exists()) { |
|
dirFile.mkdirs(); |
|
} |
|
file.createNewFile(); |
|
} |
|
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true))) { |
|
String outputMessage = message.replaceAll("~", "\r\n") + "," + "\r\n"; |
|
bufferedWriter.write(outputMessage); |
|
} |
|
} catch (IOException e) { |
|
FineLoggerFactory.getLogger().error("output fail", e); |
|
} |
|
} |
|
|
|
/** |
|
* 用于判断是不是特定的堆栈 |
|
*/ |
|
public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) { |
|
return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative; |
|
} |
|
|
|
/** |
|
* 用于判断某个堆栈是否在等待另一个事件 |
|
* 取当前堆栈前三层判断是是不是匹配等待堆栈的格式 |
|
*/ |
|
public static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) { |
|
|
|
return currentStack != null && currentStack.length >= 3 && |
|
stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) |
|
&& stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) |
|
&& stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false); |
|
} |
|
|
|
}
|
|
|