Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2005

Tip: Looking for answers? Try searching our database.

Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!)

Thread view: 
res7cxbi@verizon.net - 16 Dec 2005 06:14 GMT
How do you make java byte arrays, fill them with values, and return
them in c++? I have no clue where to start. The JNI Tutorial a at
Java's website isn't much help because it doesn't really explain how to
make new jarrays. Any tips, how-tos and example code are welcome! (And
can anybody please explain me what's jsize? Is it just another integer?)
Jean-Francois Briere - 16 Dec 2005 07:12 GMT
To create a new jbytearray of size 32:

jbytearray bArray = env->NewByteArray(32);

jsize == jint
jint is platform dependent (it's long on 32 bits Windows for instance).

You should check the specification to help you.
http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html

Regards
res7cxbi@verizon.net - 16 Dec 2005 07:33 GMT
Thanks - this is a huge start for me

how do you fill it with values though...?

Thanks (Again)
res7cxbi@verizon.net - 16 Dec 2005 08:30 GMT
Let me clarify my last reply...

How do you fill the jbyteArray with values from a BYTE* array (which is
native)?
Gordon Beaton - 16 Dec 2005 09:11 GMT
> How do you fill the jbyteArray with values from a BYTE* array (which
> is native)?

Using one of these mechanisms:

- SetByteArrayRegion()

- use GetByteArrayElements(), modify the local copy using "normal"
 assignment, then use ReleaseByteArrayElements() to propagate your
 changes back to the Java array.

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

Chris Uppal - 16 Dec 2005 09:10 GMT
> how do you fill it with values though...?

You should find the JNI book helpful.  Downloadable from:

   http://java.sun.com/docs/books/jni/index.html

See especially  section 3.3, "Accessing Arrays".

   -- chris
res7cxbi@verizon.net - 16 Dec 2005 09:52 GMT
Thanks guys, it works except for one thing....
The VM crashes!!!

This is the most interesting problem ever encountered.
I've tested each line one by one and after that
I've found out that the lines that are commented out
is the code that is causing the VM to crash

All the other code works perfectly. But the loop that
copies the contents of the buffer retrieved
by GetSample() (a method implemented by me)
into the jbyte array completely screws up everything

More interestingly, this method works for the first 2 invocations
if compiled with the for loop then crashes!

Compile w/o the loop method works perfectly

Im just as confused as you are

That loop is crucial because it is what fills the arrays!
Or is there a workaround?

Here's the code for it... it completely stumped me... any ideas are
highly appreciated!

JNIEXPORT jbyteArray JNICALL Java_SomeClass_readNextArray
 (JNIEnv *env, jobject obj)
{
   BYTE *buffer = NULL;
   DWORD bufferlen = 0;
   GetSample(&buffer, &bufferlen);
   jbyteArray bArray = env->NewByteArray( bufferlen );
   jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
   //Problem Code!!!
   //for(DWORD i = 0; i < bufferlen; i++)    {
   //    jBytes[i] = buffer[i];
   //}
   env->ReleaseByteArrayElements( bArray, jBytes, 0);
   return bArray;
}
res7cxbi@verizon.net - 16 Dec 2005 10:01 GMT
Actually it might be a problem with the GetSample() implementation.
Time to check it out...... keep you guys updated
res7cxbi@verizon.net - 16 Dec 2005 10:18 GMT
If this helps, this is the error:

#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x10001640, pid=3212,
tid=3068
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_04-b05 mixed mode,
sharing)
# Problematic frame:
# C  [ArrayReaderTest.dll+0x1640]
#
# An error report file with more information is saved as
hs_err_pid3212.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#
res7cxbi@verizon.net - 16 Dec 2005 10:21 GMT
Nope... GetSample() is fine
Gordon Beaton - 16 Dec 2005 10:48 GMT
> Nope... GetSample() is fine

When everything is fine but your code is still crashing, then your
definition of "fine" needs adjusting.

Aside from your neglect to check return values (as Chris already
pointed out) there is nothing inherently wrong with the native code
you posted.

What do buffer and bufferlen contain after calling GetSample()? Are
you sure that the length is correct for the given buffer?

What happens if you completely remove the call to GetSample(), and do
something like this instead (just to test):

 BYTE buffer[] = { 1, 2, 3, 4, 5 };
 DWORD bufferlen = 5;

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

res7cxbi@verizon.net - 16 Dec 2005 11:00 GMT
works perfectly... hey now that's even more interesting...

the buffer contains PCM audio data as unsigned bytes (i believe)
the buffer is usually somewhere in the 50,000 elements at any one time
res7cxbi@verizon.net - 16 Dec 2005 11:02 GMT
Sorry my last post was supposed to go right after Gordon's Post...
Gordon Beaton - 16 Dec 2005 11:30 GMT
> works perfectly... hey now that's even more interesting...

So I suggest you look more closely at GetSample(). Does bufferlen
agree with buffer? Is the buffer allocated dynamically? If so,
shouldn't you free it at some point?

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

Chris Uppal - 16 Dec 2005 10:18 GMT
> The VM crashes!!!

Not quite the right way to put it.  The correct expression is "My code crashes,
taking the JVM with it!!!".

>     jbyteArray bArray = env->NewByteArray( bufferlen );
>     jbyte *jBytes = env->GetByteArrayElements( bArray, 0);

Never omit error-checking in JNI code.  NEVER.

Other than that nothing obvious leaps out at me.  Possibly the error is
elsewhere in your code.  Are you /certain/ that GetSample() works, and returns
the correct values in buffer and bufferlen ?  Where does the "buffer" come
from, is it malloc()/new()-ed ?  If so then where's the corresponding
free()/delete[] ?

   -- chris
res7cxbi@verizon.net - 16 Dec 2005 10:32 GMT
The "buffer" comes from an INSSBuffer which comes from the
IWMSyncReader in the Windows Media Format SDK. I want to pass samples
to my java app
res7cxbi@verizon.net - 16 Dec 2005 10:55 GMT
Im running out of time... i'll just set up a buffer in the native code
and have individual elements passed to the java app by native methods
and have a for loop to reconstruct the array... really, can't figure
this out...

Do you guys think there's a performance penalty for java repeatly
asking for the next individual element or is it more favorable passing
the entire array to the java app?
Gordon Beaton - 16 Dec 2005 11:28 GMT
> Do you guys think there's a performance penalty for java repeatly
> asking for the next individual element or is it more favorable passing
> the entire array to the java app?

Crossing the JNI boundary is expensive. Return the whole array!

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

Gordon Beaton - 16 Dec 2005 11:51 GMT
>     jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
>     //Problem Code!!!
>     //for(DWORD i = 0; i < bufferlen; i++)    {
>     //    jBytes[i] = buffer[i];
>     //}
>     env->ReleaseByteArrayElements( bArray, jBytes, 0);

Not that this has anything to do with your problem, but you can
replace all of the above code (two calls to Set/GetByteArrayElements
and the intervening loop) with a single call to SetByteArrayRegion.

As an added bonus, SetByteArrayRegion likely uses a more efficient
mechanism to transfer the data.

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

Roedy Green - 16 Dec 2005 09:30 GMT
>How do you make java byte arrays, fill them with values, and return
>them in c++? I have no clue where to start.

to initialise arrays see http://mindprod.com/jgloss/gotchas.html#ARRAY

passing arrays back and forth to C++ is tricky. You need a text book
to explain it all.  See http://mindprod.com/jgloss/jni.html
to get started.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Gordon Beaton - 16 Dec 2005 18:19 GMT
> passing arrays back and forth to C++ is tricky. You need a text book
> to explain it all.

No it's not and no you don't.

If you have a moderate grasp of C or C++, then it's just an API like
any other. If you don't, then you probably shouldn't be using JNI.

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

Roedy Green - 17 Dec 2005 03:14 GMT
>If you have a moderate grasp of C or C++, then it's just an API like
>any other. If you don't, then you probably shouldn't be using JNI.

It the time I was learning, it was an unusually poorly documented API
without any sample code or tutorials.  It all made sense once I got a
text book that showed some sample code.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

res7cxbi@verizon.net - 17 Dec 2005 18:11 GMT
PROBLEM SOLVED!!!

I simply memcpy'd twice on some temporary BYTE*s then copy them into
jbyte using a for loop

BYTE* tempMem;
DWORD len = 0;
hr = inssBuffer->GetBufferAndLength(&tempMem, &len);
BYTE* tempMem2 = new BYTE[len];
jbyteArray bArray = env->NewByteArray( len);
jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
if(hr == S_OK)    {
   memcpy(tempMem2, tempMem, len);
   for(DWORD i = 0; i < len; i++)    {
       jBytes[i] = tempMem2[i];
   }
}
//then clean up (cleanup code ommited for clarity
env->ReleaseByteArrayElements( bArray, jBytes, 0);
return bArray;

so now i am able to return the entire array

This works perfectly this time. Thanks for all who tried to help me.
It is very much appreciated - thaks for reminding me to put in
error-checking code and giving me some ways to test it out and giving
me tips

Thank you all again!
res7cxbi@verizon.net - 17 Dec 2005 18:15 GMT
Sorry, i copy and pasted the code all wrong

BYTE* tempMem;
BYTE* tempBuffer;
DWORD len = 0;
hr = inssBuffer->GetBufferAndLength(&tempBuffer, &len);
BYTE* tempMem2 = new BYTE[len];
jbyteArray bArray = env->NewByteArray( len);
jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
if(hr == S_OK)    {
   memcpy(tempMem, tempBuffer, len);
   memcpy(tempMem2, tempMem, len);
   for(DWORD i = 0; i < len; i++)    {
       jBytes[i] = tempMem2[i];
   }

}
Gordon Beaton - 17 Dec 2005 18:39 GMT
> Sorry, i copy and pasted the code all wrong
>
[quoted text clipped - 12 lines]
>     }
> }

I hate to disappoint you, but I don't believe for a moment that
copying the data twice with memcpy (and a *third* time in the loop!)
actually solves anything:

 http://catb.org/~esr/jargon/html/C/cargo-cult-programming.html

Also, where do you initialize tempMem? Where do you free tempMem2?

/gordon

Signature

[  do not email me copies of your followups  ]
g o r d o n + n e w s @  b a l d e r 1 3 . s e

res7cxbi@verizon.net - 31 Dec 2005 07:47 GMT
Hey this is an interesting:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4418152

Maybe take a look at that


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.