Forum: PC-Programmierung Java Memory Leak bei RS232


von nochnCheffe (Gast)


Lesenswert?

Moin,

ich habe für ein Projekt Software-Teile dieser Website abgekupfert:
http://www.arduino.cc/playground/Interfacing/Java

Speziell geht es hier um den Abschnitt Sample Java Code und dann um
diesen Abschnitt:
1
/**
2
   * Handle an event on the serial port. Read the data and print it.
3
   */
4
  public synchronized void serialEvent(SerialPortEvent oEvent) {
5
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
6
      try {
7
        int available = input.available();
8
        byte chunk[] = new byte[available];
9
        input.read(chunk, 0, available);
10
11
        // Displayed results are codepage dependent
12
        System.out.print(new String(chunk));
13
      } catch (Exception e) {
14
        System.err.println(e.toString());
15
      }
16
    }
17
    // Ignore all the other eventTypes, but you should consider the other ones.
18
  }


Alles was über die RS232 rein kommt, wird ausgegeben. Aber es wird immer 
mehr Heap-Memory verbraucht. Auf dem PC läuft sonst nichts, außer eben 
mein Programm und Java VirtalVM.

Ich habe da die Zeilen
1
int available = input.available();
2
byte chunk[] = new byte[available];

in Verdacht. Kann ich das anders lösen?

Gruß
nochnCheffe

von Εrnst B. (ernst)


Lesenswert?

nochnCheffe schrieb:
> Kann ich das anders lösen?

Nicht wirklich. Java alloziert halt immer soviel speicher "wie geht", 
und versucht den Garbage Collector-Lauf, der den wieder freigeben würde, 
hinauszuzögern.
Wenn auf der Maschine sonst nix anderes läuft, wie du sagst, ist das 
auch die Richtige™ Strategie.

Wenn du lieber mehr freien + ungenutzen Ram hast: versuch die Garbage 
collection manuell anzustoßen: "System.gc()" oder so.

Oder konfigurier der VM weniger Speicher.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Εrnst B✶ schrieb:
> versuch die Garbage
> collection manuell anzustoßen
Bitte nicht, das ist kontraproduktiv!

Εrnst B✶ schrieb:
> Oder konfigurier der VM weniger Speicher
Das schon eher...

nochnCheffe schrieb:
> Ich habe da die Zeilen in verdacht
Die beiden Zeilen sind korrekt, dafür ist das lesen und die AUsgabe 
nicht 100% koscher, führen aber zu keinem Memmory leak.

von nochnCheffe (Gast)


Lesenswert?

Läubi .. schrieb:
> Die beiden Zeilen sind korrekt, dafür ist das lesen und die AUsgabe
> nicht 100% koscher, führen aber zu keinem Memmory leak.

Moin, wie macht man es besser?


Gruß
nochnCheffe

von Karl H. (kbuchegg)


Lesenswert?

Man könnte sich ja auch den chunk als Member in der Klasse halten und 
nur dann einen neuen anfordern, wenn eine größere Speicherfläche 
benötigt wird. Dann wird am Anfang der Speicherverbrauch etwas steigen, 
bis sich dann das System auf die maximal vorkommende Größe eingependelt 
hat und ab dort konstant bleiben.

von Εrnst B. (ernst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> und ab dort konstant bleiben.

Dazu müsste das
  new String(chunk)
aber auch noch irgendwie wegoptimiert werden.

dann lieber die jvm mit z.B. "-Xmx16M" starten, und nur 16Megs Ram zur 
Verfügung stellen.

Bleibt die Frage nach dem Warum. Wenn der Rechner eh nix anderes zu tun 
hat, lass die JVM doch ihr Ding machen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

nochnCheffe schrieb:
> Moin, wie macht man es besser?

Read hat einen Rückgabewert welchen man auswerten sollte, außerdem 
sollte man bei der Umwandlung byte zu char immer das Charset angeben:
1
int read = input.read(chunk, 0, available);
2
if (read > 0) {
3
  System.out.print(new String(chunk, 0, read, "UTF-8"));
4
}

Karl Heinz Buchegger schrieb:
> Man könnte sich ja auch den chunk als Member in der Klasse halten
Wenn es sich um einen einbyte Zeichensatz hadelt ginge auch:
1
while(input.available() > 0) {
2
  System.out.println((char)input.read());
3
}

Für Multibyte ist das Beispiel aber eh nicht ausgerüstet... Falls du 
wirklich Zeichen lesen willst wäre ein Reader mit einem 
BufferedInputStream welcher in einem eigenem Thread ausgeführt wird eh 
besser geeigent, in den Meisten Fällen will man eh Zeilenweise lesen, da 
ist der Eventbasierte Ansatz eh nicht so pralle...
1
    BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(input, 100)));
2
    String line;
3
    while ((line = reader.readLine()) != null) {
4
      System.out.println(line);
5
    }

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.