Win a copy of Node.js Design Patterns: Design and implement production-grade Node.js applications using proven patterns and techniques this week in the Server-Side JavaScript and NodeJS forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

JNI issue with ByteArray

 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I was wondering if someone could tell me what the following might be a symptom of. I'm making a JNI call from Java to C. Inside the C routine I allocate a ByteArray and populate it with a series of Floats. On the return from the JNI call I go through and parse through the byte array doing a endian swap on all the floats. Nearly all of the floats are correct, but around the middle of the array I start getting NAN returned from my readFloat() call. All the floats before and after this certain section are correct. I've verified on the C side that the byte array is being populated correctly so I'm confident it's not on that end. Note, this doesn't happen on every call to the routine either. I'm using latitude/longitude coordinates for the floats and in some instances the numbers are not reading correctly by the DataInputStream.

Any ideas? If the memory was off in the byte array then wouldn't the floats before or after the trouble section be wrong as well? What would cause readFloat to return NaN?

Code snippet from how I'm reading from the byte array on the java side



Thanks for any help diagnosing!

 
author and iconoclast
Posts: 24203
44
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Welcome to JavaRanch!

Probably it's the way the byte array is being created, populated, and/or returned from the C side -- let's see how you're doing it.
 
Dennis Quelch
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sure, here is what I'm doing on the C side:



Like I said in my previous post. 95% of the time all the floats pass through just fine, then every so often on the java side the readFloat() call returns NaN. Even though the data going into the byte array looked fine.

Thanks so much for your time helping me figure this out!

Dennis
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24203
44
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Unfortunately I don't see anything obvious here.

Is there possibly anything inside generateLatLonPoints() which is not threadsafe? Might the problems occur when two calls happen almost simultaneously?
 
Dennis Quelch
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Unfortunately I've added some extra code to dump out the data to a file so that I can see what the exact data is when the NaN is encountered. It always looks correct to me, and nothing obvious. There is definitely something happening between the shared library and JNI call when certain floats are sent in. I thought that maybe my compiler was producing a shared library that wasn't quite compatible with what the virtual machine was expecting with regards to a floating point number. Though I would expect this behavior to show up more often than it does though.
 
Marshal
Posts: 22461
121
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One thing I find a bit dangerous is your assumption that one LatLon struct is always going to be 8 bytes (the size of a Java float). Whereas a Java float is always 4 bytes, there is no such requirement for C programs / libraries. I would definitely change that part of the writing, to ensure you write 8 bytes each time. Maybe something like this:
sizeof(jfloat) will return 4, so this code is no longer dependent on any compiler specific settings.

Note that in your reading loop you are reading only one float whereas two are written.
 
Dennis Quelch
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks! I'll give that a try. And yes, my java example was missing that extra readFloat(). I had just copied over some code to illustrate what I was doing. The original has both reads in it. I'll post back after testing. Thanks!

 
Dennis Quelch
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey guys, just wanted to give you an update. I tracked down the problem and it was in the EndianUtil.swapFloat() routine. The standard EndianUtil library that you can find anywhere on the web for swapping a float has issues in about 1% of floats that are sent into it. By reading a float using the readFloat() routine of DataInputStream, converting it to bits using Float.floatToIntBits(), swapping the Integer, then converting it back to float using Float.intBitsToFloat() causes a precision error in certain cases resulting in junk being returned.

The solution is to write a new set of routines that read the bits from the bytestream directly into integers, then perform the byte swapping and converting it back to a float.

Problem solved! Moral of the story, always be wary of seemingly common utilities found on the web.

Thanks

Dennis
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24203
44
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's great! Thanks very much for the update; this was a real stumper.
reply
    Bookmark Topic Watch Topic
  • New Topic