# lange Strings senden



## muge (18. Mai 2005)

Hallo zusammen.

Die Zeile 3 des folgenden Codeschnipsels wirft manchmal eine Exception:
 java.lang.ArrayIndexOutOfBoundsException: 256


```
socket = new Socket(ip, port);
out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(msg.toString());
```

msg ist ein Objekt, welches eigentlich nur eine Datenstruktur ist (mit get/set Methoden).

Die Zeile hat schon unzählige solche msg Objekte versandt, ohne Probleme. Erst seit kurzem passiert manchmal die genannte Exception, bis jetzt nur dann, wenn die msg einen StackTrace enthält, welcher zu einem String zusammengehängt wurde. Grundsätzlich macht dies aber keine Probleme.

Derzeit kann ich den Fehler nicht gezielt Reproduzieren :? , das heisst mit debugging wird nichts.

Strings mit bis zu 20000 Zeichen können ohne Probleme verarbeitet werden. Die msg's, welche diese Exception auslösen, sind wesentlich kürzer.

Hat jemand eine idee, wie wo und warum diese Exception ausgelöst wird? Was bedeutet eine ArrayIndexOutOfBoundsException bei writeObject()?

thx
muge


----------



## Bleiglanz (18. Mai 2005)

warum machst du writeObject?

und dann msg.toString?

schick doch msg selbst (sofern serialisierbar), writeUTF oder verwende einen Writer um einen String zu verschicken?

wird vielleicht oft der gleiche String geschickt? schau mal die API doc zu writeUnshared an...


----------



## muge (18. Mai 2005)

Ich weiss nicht mehr genau, weshalb ich writeObject den Vorzug vor writeUTF gegeben habe. Das senden des objektes habe ich deshalb nicht gemacht, weil der auswertende Prozess nicht unbedingt Java sein soll, auch wenn er es derzeit ist.

Im msg Objekt werden informationen zum loggen transportiert. es wird nie zweimal der gleiche String geschickt.


----------



## Bleiglanz (18. Mai 2005)

muge hat gesagt.:
			
		

> Ich weiss nicht mehr genau, weshalb ich writeObject den Vorzug vor writeUTF gegeben habe. Das senden des objektes habe ich deshalb nicht gemacht, weil der auswertende Prozess nicht unbedingt Java sein soll, auch wenn er es derzeit ist.
> 
> Im msg Objekt werden informationen zum loggen transportiert. es wird nie zweimal der gleiche String geschickt.



Puu, die andere Seite nicht in Java??

in dem fall würde ich rohe bytes senden, damit keine verwirrung mit dem encoding entsteht (das müsste man in diesem Fall fixieren)


----------



## muge (18. Mai 2005)

writeObject ruft über eine Methode writeString die writeByte Methode auf. Habe ich im StackTrace gesehen.

Ich weiss einfach nicht, woher die Exception kommt und wieso.


----------



## Bleiglanz (18. Mai 2005)

na und, es werden IMMER bytes gesendet!?


----------



## muge (18. Mai 2005)

Eigentlich werden ja immer Bits gesendet... 

Ich habe aber nicht das Problem dass ich die Daten nicht lesen kann. Mein Problem ist dass manchmal eine ArrayIndexOutOfBoundsException geworfen wird, die ich nicht reproduzieren kann und keine Ahnung habe, wieso sie geworfen wird.


----------



## Bleiglanz (18. Mai 2005)

ich auch nicht

ist am string irgendwas besonderes?

sonderzeichen?

ich würde trotzdem drauf tippen, dass da irgendwas mehrfach geschickt wird (und der objectstream mit seinen back-referenzen durcheinander ist...)


----------



## muge (18. Mai 2005)

Nein, nichts besonderes. das besonderste Zeichen ist ein "$". Es funktioniert auch in 99% aller Fälle und in diesen Fällen sind die Daten korrekt.

Der String der übermittelt wird sieht so aus:

1116414101507    -1    0    0    DEPRECATED LOG ENTRY:0:A IOException occured, Exception is: java.net.ConnectException: Connection refused: connect StackTrace: java.net.PlainSocketImpl.socketConnect(Native Method) java.net.PlainSocketImpl.doConnect(Unknown Source) java.net.PlainSocketImpl.connectToAddress(Unknown Source) java.net.PlainSocketImpl.connect(Unknown Source) java.net.SocksSocketImpl.connect(Unknown Source) java.net.Socket.connect(Unknown Source) java.net.Socket.connect(Unknown Source) ch.retis.wms4.common.interprocesscom.Ipc.connect(Ipc.java:52) ch.retis.wms4.common.interprocesscom.Ipc.syncSend(Ipc.java:84) ch.retis.wms4.common.interprocesscom.IpcClient.send(IpcClient.java:51) ch.retis.wms4.client.masterconsole.JobDetailsProxy.getUptime(JobDetailsProxy.java:42) ch.retis.wms4.client.masterconsole.ObjectArrayWindow.getProcessMessage(ObjectArrayWindow.java:79) ch.retis.wms4.client.masterconsole.ObjectArrayWindow.getNewProcessUpdate(ObjectArrayWindow.java:90) ch.retis.wms4.client.masterconsole.ObjectArrayWindow.access$2(ObjectArrayWindow.java:87) ch.retis.wms4.client.masterconsole.ObjectArrayWindow$2.run(ObjectArrayWindow.java:62) java.util.TimerThread.mainLoop(Unknown Source) java.util.TimerThread.run(Unknown Source)

Die Linefeeds sind zur besseren Lesbarkeit eingefügt worden, sind aber nicht im übertragenen String


----------



## Bleiglanz (18. Mai 2005)

is aber nicht der string, sondern seine serialisierte version; ist zwar egal...

wieviele strings schreibst du eigentlich in den Stream? immer nur eins??


----------



## muge (18. Mai 2005)

Das ist der String.
Der StackTrace wird in einen String verwandelt und der wird hinten an die zusätzlichen Daten (ebenfalls Strings) angehängt. Als Trennzeichen werden Tabulatoren verwendet. Das Stringende ist ein Linefeed (solche Fehler merkt aber nur der Empfänger)

Es werden mehrere Strings in den Stream geschrieben. nach jedem schreiben wird der Stream geflusht.

Hat der ObjectStream einen Buffer?


----------



## muge (18. Mai 2005)

Jetzt kommt noch eine Plattformabhängigkeit hinzu. Unter Linux und Netbeans bringe ich den Fehler gar nicht mehr zustande. Mit Eclipse und windows ist er ziemlich regelmässig  :?


----------



## Bleiglanz (18. Mai 2005)

Note that there is a significant difference between writing a String into the stream as primitive data or as an Object. A String instance written by writeObject is written into the stream as a String initially. Future writeObject() calls write references to the string into the stream.


----------



## muge (18. Mai 2005)

Ok, habe es jetzt mal gewechselt. writeUTF(). gebracht hat es aber nicht wirklich viel. Anstelle der Exception blockiert es nun beim schreiben. Wie bei C, wenn der andere Prozess nicht liest...


----------



## Zilchinger (18. Mai 2005)

Wichtig ist, das Du den Stream, nachdem du reingeschrieben hast erstmal schließt, sonst kann der Lesende nicht drauf zugreifen. Da gibt es bei Strings immer Probleme


----------



## muge (19. Mai 2005)

ich will den Stream nicht schliessen, weil ich nicht für jede Message die Verbindung neu aufbauen will und schliessen des streams bewirkt ein schliessen des Sockets.

Ausserdem, es funktioniert ja alles, bis auf ganz wenige ausnahmen und die muss ich auch noch in den griff kriegen.


----------



## muge (20. Mai 2005)

Das Problem ist gelöst. Die Klasse, welche die nachricht sendet, ist statisch und es haben mehrere Threads darauf zugegriffen. Da gab es offenbar unterbrüche durch den Scheduler an ungünstigen stellen :-/.
Ich habe den kritischen Teil jetzt synchronized gemacht und es läuft wie gewünscht.

Was ich weiterhin etwas seltsam finde ist, dass der Fehler unter Linux nicht aufgetreten ist. Als würde die VM für Linux das ganze bereits Threadsafe behandeln und die VM von Windows nicht.

Danke für die Hilfe.
cu


----------

