Im, создающий приложение, которое (подведя итог в самых простых выражениях) действует как интерфейс к другому приложению, поэтому вместо того, чтобы просматривать вещи через консоль, я могу увидеть их в хорошем окне Swing. Я сделал более раннюю версию этого, которая просто выводит все в JTextArea как обычный текст. Он работал нормально, и у меня не было проблем с этим. Но, чувствуя потребность в расширении этой самой базовой программы немного, я решил попробовать и раскрасить сообщения, чтобы кто-то, кроме меня, мог найти путь вокруг вывода немного легче. Первая часть программы включает в себя следующее:JEditorPane мерцает при обновлении и выдает необъяснимо большие объемы использования памяти
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;
}
}
Мои извинения, если вещи, кажется, немного грязный и некоторые вещи не имеет смысла, так как это довольно поздно, и я был возиться с кодом странными способами, чтобы попытаться чтобы это работало по желанию.
СЕЙЧАС, как вы можете видеть, при запуске нить забирает время выполнения, а затем через цикл просто выплевывает то, что получает в метод. Этот метод (код, показанный ниже) отвечает за доставку контента в JEditorPane. Вот как работает функция MainWindow.writeToOutput().
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());
}
Приносим извинения, если код трудно понять или бессмысленно. Как я уже говорил, поздно, и я просто возился с ним разными способами, пытаясь заставить его работать.
В принципе, вход идет следующим образом. Аргумент 1 - это сообщение, а аргумент 2 - тип сообщения, представленного как int. 0 используется для представления сообщений, поступающих из среды выполнения, отображаемой ранее, 1 для общей информации, 2 для предупреждений, а 3 - для ошибок/исключений. Если аргумент 2 равен нулю, тогда первый фрагмент сообщения (обычно отформатированный как таковой: «[HH: MM: SS Type]») будет расчленен для определения его типа.
Код, который я сделал, очень временный и неуклюжий, и я это понимаю, однако это не тема обсуждения прямо сейчас. Проблема в том, что во-первых, каждый раз, когда на JEditorPane выводится что-то новое, панель кратковременно пустая (на долю секунды), прежде чем текст снова появится с новым сообщением внизу. Честно говоря, когда это происходит из одного сообщения, его трудно заметить, но когда процесс выплескивает сообщения влево и вправо, программа будет мерцать и слишком много вспыхивать, а также вырезать и прокручивать вниз до случайных точек в приложении, необъяснимо, поскольку автопрокрутка борется с поддерживать.
Вторая проблема - проблема с памятью. Что происходит, когда приложение запускается первым, и до того, как процесс действительно начал развиваться, он спокойно сидит вокруг 50 МБ использования памяти и не доводит до минимума ни один из моих драгоценных циклов процессора. Но как только процесс дает сообщения быстрее и быстрее, использование памяти, по-видимому, возрастает экспоненциально. Переход от 50 МБ, до 100 МБ, до 500 МБ, и обычно до максимальной загрузки от 1,5 до 1,8 ГБ.
Сначала я не был уверен, что это вызвано JEditorPane, но затем я провел небольшой эксперимент. Я вернулся к использованию JTextArea и оставил почти все одинаково и уверенно, даже когда процесс выплескивал информацию, подобную сумасшедшей, я только видел пики около 70 МБ использования памяти, а мерцающая и автопрокрутка, которую я описал, существует.
Вот что я видел в тестировании:
- JTextArea | Выходные данные содержали 47553 символа, а использование памяти было 52 МБ
- JEditorPane | Выход содержал 50531 символов, и использование памяти был 1550MB
ТАКЖЕ: На одной заключительной ноте я хотел бы сказать, что я до сих пор не очень опытный с Java, или когда дело доходит до создания приложений с помощью визуальных интерфейсов Генеральная. Большое спасибо всем, кто отвечает.
Трудно быть уверенным, но вы, кажется, нарушаете правила нитей Swing, которые не помогут. См. [Параллелизм в Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/). Текстовые компоненты имеют тенденцию требовать большой объем памяти для того, что считается небольшим количеством текста. Возможно, лучше было бы взаимодействовать с «Документом» текстовых компонентов и вставлять текст, а затем использовать «setText» – MadProgrammer
Некоторые альтернативы [здесь] (http://stackoverflow.com/q/25526833/230513); вы можете 'exec()' из 'doInBackground()'. – trashgod