Help - JNI and JMS - data conversion problems

G

Gordon Beaton

I have a .c program using jni and sending and receiving messages via
jms. All seems to work well, except for 1 problem.

If I embed some binary bytes (e.g. 0x00,0x01,0x02,0x03,0x04) in the
middle of the buffer,
[...]

Then in the c program I get a "jstring" object back from Java via
the the CallObjectMethod and then do a "GetStringUTFChars" to
convert the jstring to the char * .c string. It seems that the
binary 0x00 is changed to 0xc080.

Don't assume that your binary data can be treated as though it were
text, which it isn't. Strings and binary data are different animals.
Unless you have good reason to, you shouldn't be converting between
them. And when you do, you should almost always specify what encoding
to use. For example, see the API documentation for the String
constructor that takes a byte array and a character encoding, and the
String method getBytes(encoding).

Realize too that UTF is not the same thing as ASCII or Latin1, or
whatever you were expecting to find in the char*.
Anyone know what is the correct way to do this?

To do *what*?

/gordon
 
G

gailw

I have a .c program using jni and sending and receiving messages via jms.
All seems to work well, except for 1 problem.

I am sending and receiving data thru jni and jms.
If I embed some binary bytes (e.g. 0x00,0x01,0x02,0x03,0x04) in the middle
of the buffer, the data goes all the way thru the send side to the server
(currently using Sun's j2ee for testing). On the receive side it comes all
the way back. In various locations in the java code, I am outputting the
messages and it looks good; the binary data is still intact. All looks
well.

Then in the c program I get a "jstring" object back from Java via the the
CallObjectMethod and then do a
"GetStringUTFChars" to convert the jstring to the char * .c string. It
seems that the binary 0x00 is changed to 0xc080. The 0x01,0x02,0x03,0x04
remains unchanged. I even tried it with multiple occurrences of the
0x00,0x01,0x02,0x03,0x04 and it's always the same - the 0x00 is changed to
0xc0,0x80; the 0x01,0x02,0x03,0x04 remains good.

I'll add a routine to pass the returned jstring back to java to see if it's
still OK, but I suspect that it probably will be good. Seems to me the
GetStringUTFChars is botching it up.
I guess the 0xc080 is unicode for the 0x00, but I'm currently baffled as to
how to fix this.

Anyone know what is the correct way to do this?

For direct email, change the i to a 1.

Thanks,

Jim W.
 
G

Gordon Beaton

Then I jni it to my Java program as a byte[] field. Then the Java
program converts this to a String using "new
String(byte[],offset,len)".

Whenever you convert between byte[] to String, you should seriously
consider using one of the String constructors that accepts a character
encoding in addition to the byte array. Without it, you are blindly
accepting the JVM's choice of encoding. While that might work most of
the time, it won't work all of the time.
From then on, it is handled as String data. Are you saying this is
where the flaw is - should I use a different String constructor, or
should I just use byte[] data all the way thru and not use JMS
TextMessage, but use JMS ByteMessage.

If the data really isn't text (and you implied in your first post that
it isn't) then you shouldn't be treating it as text at all. In other
words, I suggest you lose the conversion to String completely.
The GetStringUTFChars only accepts a jstring (Java String) so
somewhere I must end up with a String in the Java code.

You can pass byte arrays back and forth between Java and C without any
conversion at all. Why "must" you end up with a String?

Alternatively, why are you inserting binary data into what used to be
a String?

/gordon
 
G

gailw

As must be obvious, I'm not a real experienced Java guy so a little patience
with me please. I'm trying to figure out if my problem in in the Java side,
the JNI side, or the way I do the JMS.

Currently, in the C program I convert the data to be sent into a jbyteArray
and fill it.
Then I jni it to my Java program as a byte[] field. Then the Java program
converts this to a String using "new String(byte[],offset,len)".
From then on, it is handled as String data.
Are you saying this is where the flaw is - should I use a different String
constructor, or should I just use byte[] data all the way thru and not use
JMS TextMessage, but use JMS ByteMessage.

The GetStringUTFChars only accepts a jstring (Java String) so somewhere I
must end up with a String in the Java code.

Thanks,

Jim W.


Gordon Beaton said:
I have a .c program using jni and sending and receiving messages via
jms. All seems to work well, except for 1 problem.

If I embed some binary bytes (e.g. 0x00,0x01,0x02,0x03,0x04) in the
middle of the buffer,
[...]

Then in the c program I get a "jstring" object back from Java via
the the CallObjectMethod and then do a "GetStringUTFChars" to
convert the jstring to the char * .c string. It seems that the
binary 0x00 is changed to 0xc080.

Don't assume that your binary data can be treated as though it were
text, which it isn't. Strings and binary data are different animals.
Unless you have good reason to, you shouldn't be converting between
them. And when you do, you should almost always specify what encoding
to use. For example, see the API documentation for the String
constructor that takes a byte array and a character encoding, and the
String method getBytes(encoding).

Realize too that UTF is not the same thing as ASCII or Latin1, or
whatever you were expecting to find in the char*.
Anyone know what is the correct way to do this?

To do *what*?

/gordon
 
R

Roedy Green

If I embed some binary bytes (e.g. 0x00,0x01,0x02,0x03,0x04) in the middle
of the buffer, the data goes all the way thru the send side to the server
(currently using Sun's j2ee for testing).

You are passing a raw byte array. What it could be is a
DataOutputStream in a raw byte array.

to create such a beast see http://mindprod.com/fileio.html

You can read it with a DataInputStream.

Note when you do this your Strings will be counted UTF-8 format.
You could write them an char[] if you wanted the simplicity of 16-bit
chars.

Trying to encode binary data in Strings is asking for trouble unless
you use something very vanilla like base64.

see http://mindprod.com/jgloss/base64.html
 
G

gailw

Thanks for prompt replies.

The reason for embedding the binary data in text data was purely to test
whether I could handle binary data. So I'm just reading a file for now
where I inserted some binary data, and then send the file byte stream.
We are extending an MQSeries application to be able to also use JMS and
there are occasions where it must place "raw" (binary) data on the Queues.
I currently have no problem with the pure ascii type text, but the "raw"
data is giving me a big headache.

I'll experiment with just forgetting the String stuff and using byte[]
and/or char[] data.

--

Jim W.

Roedy Green said:
If I embed some binary bytes (e.g. 0x00,0x01,0x02,0x03,0x04) in the middle
of the buffer, the data goes all the way thru the send side to the server
(currently using Sun's j2ee for testing).

You are passing a raw byte array. What it could be is a
DataOutputStream in a raw byte array.

to create such a beast see http://mindprod.com/fileio.html

You can read it with a DataInputStream.

Note when you do this your Strings will be counted UTF-8 format.
You could write them an char[] if you wanted the simplicity of 16-bit
chars.

Trying to encode binary data in Strings is asking for trouble unless
you use something very vanilla like base64.

see http://mindprod.com/jgloss/base64.html
 
G

gailw

Hmmmm...
I went to change the conversion from byte[] to String to use the encoding
specification and the only place I really convert byte[] to String is in the
send side. But the receive side is where the problem seems to occur - in
the GetStringUTFChars function. I used byte[] as input to the send side
because that was the only way to get the binary data thru JNI - I could
either create a jstring (Java String) or a jbytearray and the byte array is
the only way to get the binary data in - hence I send a byte[] to Java via
JNI this way.

I'll just try to return byte[] to c on the return side instead of a String -
see how that goes. And then maybe use byte[] all the way around.

Still a bit confused here.

Thanks again,

Jim W.

Gordon Beaton said:
Then I jni it to my Java program as a byte[] field. Then the Java
program converts this to a String using "new
String(byte[],offset,len)".

Whenever you convert between byte[] to String, you should seriously
consider using one of the String constructors that accepts a character
encoding in addition to the byte array. Without it, you are blindly
accepting the JVM's choice of encoding. While that might work most of
the time, it won't work all of the time.
From then on, it is handled as String data. Are you saying this is
where the flaw is - should I use a different String constructor, or
should I just use byte[] data all the way thru and not use JMS
TextMessage, but use JMS ByteMessage.

If the data really isn't text (and you implied in your first post that
it isn't) then you shouldn't be treating it as text at all. In other
words, I suggest you lose the conversion to String completely.
The GetStringUTFChars only accepts a jstring (Java String) so
somewhere I must end up with a String in the Java code.

You can pass byte arrays back and forth between Java and C without any
conversion at all. Why "must" you end up with a String?

Alternatively, why are you inserting binary data into what used to be
a String?

/gordon
 
G

gailw

I think this is working now. Where I send the data as a byte[] from C to
Java; in Java, I convert the byte[] to a String using UTF8 as the encoding
and it seems to come out on the other side (receive side) intact.

Weird. Without this little thing, it was rattling around in Java and
everywhere I checked, the data was still intact - only when finally
converting in the C side did it get messed up.

Thanks for the hints.

Jim W.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

JNI get exception object class name 1
Can't solve problems! please Help 0
JNI 1
jms + eclipse 1
JNI Invocation API example 4
Threads and JMS 1
JNI and JMS conflict 1
JMS, RMI and synchronous request-response 9

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top