JNA 3.4.0 on the NetBeans Platform

This is a little problem that’s been bugging me for a while – how to use a newer version of JNA (Java Native Access) with a NetBeans platform application.  The recently released JNA 3.4.0 brings some major performance improvements for callbacks, and as this improvement was requested by me (particularly for JNAJack) I’m damn well going to use it! :-)

UPDATE 21/6/12 – after reading this be sure to read JNA 3.4.x on the NetBeans Platform (revisited) which covers in more detail some of the questions in the comments here.

So, what’s the problem?

Well,

  • JNA is in the platform, but it’s an old version.
  • A number of platform modules require JNA.
  • JNA includes a native library, which precludes having multiple versions of JNA in the module system.
  • JNA in the platform only allows friend dependencies (don’t get me started on the annoyance of friend dependencies on modules that provide native libs!)

And, the solution -

  • Create a new library wrapper module for JNA 3.4.0. Give the wrapper module the same code name base as the core JNA module – org.netbeans.libs.jna
  • Give the new wrapper module the same major release version as the platform JNA (1), and a specification version higher than the platform JNA (I chose 3.4.0 as the logical choice)
  • Make sure JNA is enabled in the platform. This confused me for a while, but the excluded modules list has no sense of clusters, so if you exclude JNA from the platform, your new module will also be excluded!  (that would probably make a good RFE)
  • Make sure you’ve got a module in your application that has a dependency on the new JNA module (ie. depends on version 3.4.0).  Not sure how necessary this is, but it seems to ensure the right module is loaded, and you’ll need the dependency to rely on the new features anyway.

Run your application and look at the module list in the log.  You should see the new version of JNA being loaded.

So, are we done?

Well, not quite.  This allows us to run our application from the IDE with the new JNA module.  However, if you build a zip distribution you’ll notice that the old JNA module is still in the platform folder.  It shouldn’t cause a problem, but it takes up space and for safety’s sake it would be better to get rid of it.

To do that, I copied the build-zip target from the build harness into the build.xml file of my application, and made a few changes (see comment).

<target name="build-zip" depends="build,build-launchers" description="Builds a ZIP distribution of the suite, launchers, and selected modules from the platform.">
  <mkdir dir="${dist.dir}"/>
  <!-- pathfileset does not support 'prefix' and 'filemode' parameters,
       we have to copy them to temp location -->
  <tempfile property="temp.dir.nbexec" destdir="${suite.build.dir}" deleteonexit="true" prefix="nbexec"/>
  <tempfile property="temp.dir.rest" destdir="${suite.build.dir}" deleteonexit="delete" prefix="rest"/>
  <subant genericantfile="${harness.dir}/suite.xml" target="copy-cluster" inheritrefs="true">
    <property name="dest.dir" value="${temp.dir.rest}"/>
    <property name="nbexec.dir" value="${temp.dir.nbexec}"/>
    <property name="build.dir" value="${suite.build.dir}"/>
    <resources refid="zip.platform.clusters"/>
  </subant>
  <zip destfile="${dist.dir}/${app.name}.zip">
    <zipfileset dir="${build.launcher.dir}/bin/" filemode="755" prefix="${app.name}/bin"/>
    <zipfileset dir="${build.launcher.dir}/etc/" prefix="${app.name}/etc"/>
    <zipfileset dir="${temp.dir.nbexec}" filemode="755" prefix="${app.name}"/>
    <zipfileset dir="${temp.dir.rest}" prefix="${app.name}">
      <!-- FOLLOWING THREE LINES REMOVE JNA FROM PLATFORM -->
      <exclude name="platform/**/org-netbeans-libs-jna*"/>
      <exclude name="platform/**/jna-3.2.7.jar"/>
      <exclude name="platform/**/*jnidispatch*"/>
    </zipfileset>

    <!-- Yes, the doubled app.name is a bit ugly, but better than the alternative; cf. #66441: -->
    <zipfileset dir="${cluster}" prefix="${app.name}/${app.name}">
      <exclude name="config/Modules/*.xml_hidden"/>
    </zipfileset>
  </zip>
</target>

In particular, notice the three exclude lines that match various artefacts of the JNA module and exclude them from the zip file (and therefore also from the installers).

This all seems to be working fine, and will be used in the (slightly late) first full release of Praxis, which is based on NetBeans platform 7.0.  It may require tweaking to work with other versions of the platform.

About these ads

9 thoughts on “JNA 3.4.0 on the NetBeans Platform

  1. I’m going down this road with NetBeans 7.1
    I needed to put
    run.args.extra=-J-Djna.nosys=true
    into my project.properties file for the Module Suite project.

    • Praxis hasn’t been updated to NetBeans 7.1 yet, though I’ll be looking into this next month. It could be that the build process needs tweaking further. However, another common cause of this issue is having a system installed copy of JNA. Are you sure your application isn’t picking up the native libs from elsewhere?

      • Hi Neil,
        Thanks for the response.

        I’m not actually using Praxis. I am using NetBeans Platform. I don’t totally follow the JNA documentation about its search sequence for the .dll, but it sounds like the jna.nosys makes it more robust for now. It may be something required for NetBeans 7.1, or it may be something required for the machine I’m executing upon today.

        Either way, I’d like things to work for my end customer without hitches!

        Kind Regards,
        -John

      • Hi John,

        I understood that you are using the platform, not Praxis. It’s just that I won’t get a chance to see whether these instructions need updating until I update Praxis to NB 7.1. The jna.nosys=true is probably a good tip to use anyway, but it’s also a sticking plaster over whatever the root cause of your problem is. Don’t forget the run.args.extra property only affects running from the IDE though, so it needs to be set in your configuration file or elsewhere too, otherwise it won’t make anything more robust for your customers! :-)

        If you aren’t on it already, I recommend joining http://groups.google.com/group/jna-users Variations on this issue have cropped up there a few times.

        Best wishes, Neil

  2. Hi,

    First of all – thanks for this! Really useful!

    I’m following all the steps and made some progress, but I can’t find the right place to put my dll.

    Done so far:
    - Create wrapper project according to Neil.
    - Set the run.args.extra=-J-Djna.nosys=true variable
    - Put the library on the module/lib folder

    But it can’t find the DLL. I tried to add the jna.library.path and it works, but it’s a static solution not suitable for installations.

    Any ideas?

    Thanks, Carlos

    • Hi Carlos,

      Thanks for your comment.

      The problem you have is because JNA doesn’t use the standard Java library loading mechanism, and hence has no idea about the work the NetBeans classloader does to provide the library location in the module/lib folder.

      Firstly, to find the folder containing your DLL, use the InstalledFileLocator class. Then pass this folder into NativeLibrary.addSearchPath(..) before attempting to load your library (you could also set jna.library.path, but I find addSearchPath a cleaner way of doing it).

      There’s an example of doing this in this class from the Windows GStreamer plugin in Praxis – http://code.google.com/p/praxis/source/browse/praxis.video-gstreamer-win/src/net/neilcsmith/praxis/video/gstreamer/windows/LibraryLoaderImpl.java?repo=ext Specifically lines 116-122 and 218.

      Incidentally, I’m not keen on the jna.nosys solution – currently looking at extracting the jnidispatch library into the module/lib folder instead – same way the existing NetBeans JNA module does it.

      Best wishes, Neil

      • Hi Neil,

        Thanks so much for your quick response, now everything it’s working nice & clean :)

        I’m not a fan of the jna.nosys solution neither, but does the job for the moment. I’ll to get rid of that when I have some time.

        Kind regards, Carlos

  3. Pingback: JNA 3.4.x on the NetBeans Platform (revisited) | praxis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s