Im making an application which (to sum it up in very basic terms) acts as an interface to another application, so rather than having to view things through the console I can see them in a nice Swing window. I had made an earlier version of this, which simply output everything into a JTextArea as plain text. It worked fine, and I had no issues with it. But feeling the need to expand out this very basic program a bit, I decided to try and color coat the messages so that someone other than myself could find their way around the output a bit more easily. First part of the program involves this:
class ServerIOStream extends Thread {
private boolean _isRunning = false;
private Process _serverProcess = null;
private BufferedReader input = null;
private PrintWriter writer = null;
public void run() {
try {
_serverProcess = Runtime.getRuntime().exec(PropertiesReader.getLaunchString());
input = new BufferedReader(new InputStreamReader(_serverProcess.getInputStream()));
_isRunning = true;
String line;
while ((line = input.readLine()) != null)
MainWindow.writeToOutput(line, 0);
_isRunning = false;
MainWindow.writeToOutput("Service has stopped...", 1);
} catch (IOException ex) {
MainWindow.writeToOutput(ex.getMessage(), 3);
_isRunning = false;
}
}
public boolean ServerStatus(){
return _isRunning;
}
}
My apologies if things seem a bit messy and some stuff does not make sense, as it is quite late and I have been tinkering with the code in strange ways to try and get this to work as desired.
NOW, as you can see, upon being run the thread will pick up a runtime, and then via a loop just spit out what it receives into method. That method (Code shown below) is responsible for delivering the content to JEditorPane. Here is how the MainWindow.writeToOutput() function works.
private static String output;
public static void writeToOutput(String message, int inputType){
String finalMessage = null;
String type = null;
switch(inputType){
case 0: // For input from the server
finalMessage = message;
break;
case 1: // General info from the GUI
type = "INFO";
break;
case 2: // Warnings from the GUI
type = "WARN";
break;
case 3: // Error messages from the GUI
type = "ERROR";
break;
default: // Unknown messages
type = "UNKNOWN";
break;
}
if(inputType == 1 || inputType == 2 || inputType == 3){
finalMessage = String.format("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + " GUI %s" + "]: %s", type, message);
if(inputType == 1)
finalMessage = "<font color=\"" + PropertiesReader.getInfoColor() + "\">" + finalMessage + "</font>";
else if(inputType == 2)
finalMessage = "<font color=\"" + PropertiesReader.getWarnColor() + "\">" + finalMessage + "</font>";
else if(inputType == 3)
finalMessage = "<font color=\"" + PropertiesReader.getErrColor() + "\">" + finalMessage + "</font>";
}
else if(inputType == 0){
try{
String s = finalMessage;
s = s.substring(s.indexOf("[") + 1);
s = s.substring(0, s.indexOf("]"));
if(s.contains("INFO"))
finalMessage = "<font color=\"" + PropertiesReader.getInfoColor() + "\">" + finalMessage + "</font>";
else if(s.contains("WARN"))
finalMessage = "<font color=\"" + PropertiesReader.getWarnColor() + "\">" + finalMessage + "</font>";
else if(s.contains("ERROR"))
finalMessage = "<font color=\"" + PropertiesReader.getErrColor() + "\">" + finalMessage + "</font>";
}
catch(StringIndexOutOfBoundsException ex){
finalMessage = "<font color=\"red\">" + finalMessage + "</font>";
}
}
if(output != null)
output += finalMessage + "<br>";
else
output = finalMessage + "<br>";
ServerOutputTextArea.setText(output);
if(inputType == 0 || inputType == 1 || inputType == 2)
System.out.println(finalMessage);
else
System.err.println(finalMessage);
if(AutoScrollCheckbox.isSelected())
ServerOutputTextArea.setCaretPosition(ServerOutputTextArea.getDocument().getLength());
finalMessage = null;
message = null;
System.out.println("\nLength: " + output.length());
}
I apologize yet again if the code is hard to follow or nonsensical. As I said before, it is late and I was just tinkering with it in all sorts of ways in an attempt to get it to work.
Basically, input goes as follows. Argument 1 is the message, and argument 2 is the type of message represented as an int. 0 is used to represent messages coming from the runtime displayed before, 1 is for general info, 2 is for warnings, and 3 is for errors/exceptions. If argument 2 is equal to zero, then the first chunk of the message (Typically formatted as such: "[HH:MM:SS Type]") will be dissected to determine its type.
The code I have made is very makeshift and clunky and I understand that- however that is not the topic of discussion right now. The issue at hand is that first, each time something new is output to the JEditorPane the pane will briefly go blank (for a fraction of a second) before the text reappears with the new message at the bottom of it. Honestly when it happens from a single message its hard to notice, but when the process is spitting messages out left and right the program will flicker and flash too much, and cut and scroll down to random points in the application inexplicably as the autoscroll struggles to keep up.
The second issue is the memory issue. What happens is when the application first starts and before the process has really started to get going it sits calmly around 50MB of memory usage, and hogs little to none of my precious CPU cycles. But suddenly as the process gives messages faster and faster, memory usage seems to increase exponentially. Going from 50MB, to 100MB, to 500MB, and normally up to a max of around 1.5GB to 1.8GB of memory usage.
At first, I was not sure if this was being caused by the JEditorPane, but then I ran a small experiment. I went back to using JTextArea and left most everything the same and sure enough, even when the process was spitting out info like mad I only ever saw peaks of around 70MB of memory usage, and the flickering and autoscroll struggle that I described was non-existent.
Here is what I saw in testing:
- JTextArea | Output contained 47553 characters, and memory usage was at 52MB
- JEditorPane | Output contained 50531 characters, and memory usage was at 1550MB
ALSO: On one final note I would like to say that I am still not very experienced with Java, or when it comes to making applications with visual interfaces in general. Thank you very much to all who answer.