Recreate System.out to print again in CONSOLE after System.out.close()

社会主义新天地 提交于 2021-01-28 01:53:17

问题


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.

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");
} 

Now, is there a way to magicallyGetTheOutputStream of Console to start printing in the console again ?

Note: The application is running in java 5 and 6.


回答1:


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);

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();
    }
}


来源:https://stackoverflow.com/questions/34172384/recreate-system-out-to-print-again-in-console-after-system-out-close

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!