问题描述
我有一个桌面应用程序,当冻结了几分钟后,有一个线程监视冻结,并开始转储所有线程的堆栈跟踪信息(此操作在本机调用中完成,因此可以调用JVM_DumpAllStacks
)放入临时文件.然后,在本机调用之后,该临时文件将读取为String,并用于登录应用程序自己的日志记录框架.
I have a desktop application, when there is a freeze for some minutes, there is a thread which monitors the freeze and it starts dumping stack traces of all threads(this is done in native call so that JVM_DumpAllStacks
can be invoked) into temporary file. Then the temporary file is read as String after the native call and it is used to log in application's own logging framework.
问题是,在完成所有这些过程之后,我无法将System.out
恢复到CONSOLE流.
The problem is, After all these process, I am not able to restore System.out
to CONSOLE stream.
这在下面的代码中有更好的解释.
This is better explained in the below code.
public String getAllStackTraces() {
System.out.println("This will be printed in CONSOLE");
// This is NECESSARY for the jvm to dump stack traces in specific file which we are going to set in System.setOut call.
System.out.close();
File tempFile = File.createTempFile("threadDump",null,new File(System.getProperty("user.home")));
System.setOut(new PrintStream(new BufferedOutputStream(new FileOuptputStream(tempFile))));
//This native call dumps stack traces all threads to tempFile
callNativeMethodToDumpAllThreadStackTraces();
String stackTraces = readFileAsString(tempFile);
//close the tempFile PrintStream so as the next PrintStream object to set as 'out' and to take effect in the native side as well
System.out.close();
//Now I want to start printing in the CONSOLE again. How to do it again ?
//The below line does not work as FileDescriptor.out becomes invalid (i.e FileDescriptor.out.fd, handle = -1) after we do System.out.close() where out is PrintStream of console.
//System.setOut(new PrintStream(new BufferedOutputStream(new FileOuptputStream(FileDescriptor.out))));
PrintStream standardConsoleOutputStream = magicallyGetTheOutputStream() // How ???????????
System.setOut(standardConsoleOutputStream);
System.out.println("This will be printed in CONSOLE !ONLY! if we are able to get the new PrintStream of Console again magically");
}
现在,是否可以使用Console的magicallyGetTheOutputStream
再次在控制台中开始打印?
Now, is there a way to magicallyGetTheOutputStream
of Console to start printing in the console again ?
注意:该应用程序正在Java 5和6中运行.
Note: The application is running in java 5 and 6.
推荐答案
考虑以下代码,以了解如何存储原始System.out 而无需关闭,以便稍后将其恢复为完整的荣耀:
Consider this code of how to store away original System.out without closing to later restore it to full glory:
//Store, don't close
PrintStream storeForLater = System.out;
//Reassign
System.out(setToNew);
...
//Close reassigned
setToNew.close();
//Reset to old
System.setOut(storeForLater);
作为本机代码的替代方法,您可以调用 ThreadMXBean .返回的 ThreadInfo 对象包含有关以下内容的信息:保持锁定并锁定线程正在等待.
As an alternative to native code, you could call into ThreadMXBean. The returned ThreadInfo objects contain information about Locks held and Locks the thread is waiting for.
public static void dumpThreads(PrintStream out) {
ThreadInfo[] threads = ManagementFactory.getThreadMXBean()
.dumpAllThreads(true, true);
for(final ThreadInfo info : threads) {
out.println("Thread: " + info.getThreadId()
+ "/" + info.getThreadName()
+ " in State " + info.getThreadState().name());
if(info.getLockName() != null) {
out.println("- Waiting on lock: " + info.getLockInfo().toString()
+ " held by " + info.getLockOwnerId()+"/"+info.getLockOwnerName());
}
for(MonitorInfo mi : info.getLockedMonitors()) {
out.println(" Holds a lock on a " + mi.getClassName() +
" from " + mi.getLockedStackFrame().getClassName()+"."+mi.getLockedStackFrame().getMethodName()
+ ": " + mi.getLockedStackFrame().getLineNumber());
}
for(StackTraceElement elm : info.getStackTrace()) {
out.println(" at " + elm.getClassName() + "."
+ elm.getMethodName() + ":"+elm.getLineNumber());
}
out.println();
}
}
这篇关于重新创建System.out以在System.out.close()之后再次在CONSOLE中打印的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!