This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 126848 - add JNA library to NetBeans platform to support access to native OS features
Summary: add JNA library to NetBeans platform to support access to native OS features
Status: RESOLVED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: -- Other -- (show other bugs)
Version: 6.x
Hardware: All All
: P1 blocker (vote)
Assignee: Stanislav Aubrecht
URL:
Keywords: API_REVIEW
Depends on:
Blocks:
 
Reported: 2008-02-06 16:23 UTC by Stanislav Aubrecht
Modified: 2008-12-22 11:26 UTC (History)
5 users (show)

See Also:
Issue Type: TASK
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stanislav Aubrecht 2008-02-06 16:23:46 UTC
JNA (Java Native Access) is a Java library that allows access to native OS features: https://jna.dev.java.net/
The standard distribution of JNA includes small native binaries for each supported platform (Win, Linux/Solaris, Mac)
which handle the translation of Java calls into the native OS libraries.
JNA is needed in NetBeans platform to allow advanced visual effects in window system, e.g. (half-)transparent windows,
non-rectangular windows etc, see issue #123110. These effects are also required in JavaFX suite. It might be also
possible to use JNA for example to add native file system listeners...

Since the JNA may not be always available, either because of unsupported OS or because of some legal reasons (binaries
in Linux distros) it will be better to hide the whole JNA behind some sort of 'bridge' module. I've already created
core.nativeaccess module in core-winsysfx branch with an initial version of such bridge API/SPI: 

http://hg.netbeans.org/core-winsysfx/file/c7e4a709bab2/core.nativeaccess/

JNA library is in libs.jna:
http://hg.netbeans.org/core-winsysfx/file/c7e4a709bab2/libs.jna/
Comment 1 Stanislav Aubrecht 2008-02-07 12:12:40 UTC
Inception review took place on Feb 7th (S. Aubrecht, D. Simonek, D. Strupl, J. Tulach, R. Matous)
The current implementation and layout of JNA apis/libraries in core-winsysfx branch was approved with the following
comments:

1. change core.nativeaccess to api.nativeaccess, new module base name will be org.netbeans.api.nativeaccess
2. make api.nativeaccess a stable api, publish its JavaDoc
3. use appropriate Recommends/Provides token in api.nativeaccess and in libs.jna
4. remove unnecessary demo classes from libs.jna
Comment 2 Stanislav Aubrecht 2008-02-16 17:11:57 UTC
architecture description: http://hg.netbeans.org/core-winsysfx/file/c1422a0dab4e/api.nativeaccess/arch.xml
JNA library: http://hg.netbeans.org/core-winsysfx/file/c1422a0dab4e/libs.jna/

i'm planing to put the JNA library and Native Access API to main repository by sunday evening
Comment 3 Stanislav Aubrecht 2008-02-19 14:29:03 UTC
i'd like to integrate the JNA library and api into main repository by wednesday (feb 20th) evening
Comment 4 Jesse Glick 2008-02-19 18:32:26 UTC
I support including JNA in NetBeans. I don't agree with hiding it behind a wrapper API. IMHO if the current platform
does not support the native method(s) you are trying to call, you should get an exception which you can catch and deal
with in an appropriate way. The core.windows module can do this itself without the help of a dummy API. I definitely
don't agree with having the JNA wrapper module include window-system-specific code. I would suggest just having a simple
JNA module which exports the appropriate JNA API and which would be used directly by client code that needs it.

BTW get rid of the empty layer file.

jna.jar should include a version number in its name. And since it requires associated JAR files, best to put them all
together in a subdir, e.g. modules/ext/jna/*.jar.
Comment 5 Stanislav Aubrecht 2008-02-19 19:21:48 UTC
but with the two-module separation it would be easier
a) to turn the whole native functionality on/off by simply un/installing the JNA module
b) to deal with packaging of netbeans on some linux distros where we won't be able to build/distribute the native libraries
c) to cope with changes in JNA api so we'll easily ensure backwards compatibility when a new JNA library is released
Comment 6 Jesse Glick 2008-02-19 20:04:32 UTC
a) I don't see how this is an advantage.

b) We can always distribute jna.jar itself, i.e. the Java interfaces. If the JNA native library defining the binding for
that platform is not available, trying to initialize JNA will throw an exception, which client code can decide how best
to deal with. Client code anyway needs to handle a range of possible exceptions, in case the domain-specific native
library (e.g. libX11.so) is missing or does not match the signature expected by the client.

c) I think it is up to client code to deal with possible changes in the JNA API, which we would mark as "external" or
"under development". (If there are incompatible changes, increment the major release version to indicate this.)

The currently proposed patch does not permit any other modules to make use of JNA, it mixes window system functionality
into the JNA wrapper module, and it introduces a new API module whose contents ought to be an implementation detail of
the window system.
Comment 7 Stanislav Aubrecht 2008-02-19 20:51:55 UTC
> The currently proposed patch does not permit any other modules to make use of JNA, it mixes window system functionality
> into the JNA wrapper module, and it introduces a new API module whose contents ought to be an implementation detail of
> the window system.

isn't it possible to add implementation dependency on libs.jna module and use the JNA api directly without our wrapper?
JNA api isn't really simple and accessing native functionality needs a lot of messy java code. my idea was that we could
provide implementation for some common native tasks (e.g. window transparency) which would be extended via api changes
later on (e.g. adding native listening to file system changes - NativeFileSystem - etc)
Comment 8 Jesse Glick 2008-02-19 21:16:59 UTC
I don't want to encourage any usage of implementation dependencies.

If accessing native functionality requires some messy Java code, so be it; keep it in the module that needs it and out
of the public APIs. If and when it is decided that several independent modules all need the _same_ clearly defined
native functionality, someone can provide a static utility method in an appropriate module to avoid code duplication.
Comment 9 Jesse Glick 2008-02-19 21:23:49 UTC
Some other comments:

AFAIK jna.jar is the only file you need; why do you have darwin.jar / linux-i386.jar / win32-x86.jar? jna.jar includes
all the supported native binding libs.

It seems the (unlabelled) copy of jna.jar you are using is not the latest version, 3.0.1. All the more reason to include
the version number in the filename...
Comment 10 Stanislav Aubrecht 2008-02-19 21:38:48 UTC
well, JNA is already needed by two modules: core.windows and JavaFX window system but i suppose this can be fixed by
moving the code from libs.jna to core.windows and javafx having dependency on core.windows.

i'll check the JNA jar versions needed. but if the binaries are packaged within the jna.jar then it'll be problem
removing the native binaries where we're not allowed to distribute them, won't it?  e.g. jnidispatch.dll in linux distros...
Comment 11 Jesse Glick 2008-02-19 22:04:38 UTC
For Linux distros which require compilation from source, I imagine that the build script would simply try to compile
only the appropriate Linux native sources.
Comment 12 Jaroslav Tulach 2008-02-20 10:28:27 UTC
I really do not like the idea of exposing 3rd party API, which does not provide any guarantees about compatibility as 
part of NetBeans platform. I know this API will be found useful and I am afraid of that, as soon as we upgrade to new 
slightly incompatible version of the library, we will break backward compatibility of the whole platform.

That is why I prefer use of wrapper module, with APIs under our control. Anyone can extend its API, so from a 
developer point of view, this is not that big restriction. The most prominent user of the API - filesystems - agreed 
that this is the way to go.

I know that having all JNA API publically available is tempting, it can be done, but it may result into a situation 
where we will need to stick with older version of the library, because the promise of the platform compatibility will 
be more important than any features offered by the new version of JNA. I'd like to avoid situation described at
http://www.onlamp.com/pub/a/onlamp/2005/02/17/backwardscompatibility.html
where the project needed to stick with old version of some library just because they accidentally re-exported its APIs 
to their clients. 

Unless there is real need and pressure for exposing JNA APIs to everyone, let's keep it hidden.
Comment 13 David Simonek 2008-02-20 12:26:02 UTC
I agree with Jarda. Having our platform vulnerable to 3rd party development decisions is not acceptable to me.

Moreover, I like the idea of having all NetBeans native access defined on one place, one module, not scattered through
NetBeans code.

Also as a platform developer I would appreciate possibility to remove JNA library from platform if I couldn't go with it
for some reason, although I admit I don't have example of such reason at hand.
Comment 14 Jesse Glick 2008-02-20 15:30:47 UTC
I still disagree. What about making a simple lib wrapper as I suggested but with friend access only? Then we introduce
no new APIs (to the outside) at all. If in the future other modules need to use JNA, or we decide its API is stable
enough to expose publicly, we can simply adjust the one project.xml accordingly - and not need to make any big
architectural changes, nor deprecate some silly callback API.
Comment 15 tomwheeler 2008-02-20 15:47:10 UTC
This is very timely -- we're using JNA in one of our applications as have a lot of native code for high-performance 
mathematics.

It would be convenient if JNA was "just there" but I also fear that if JNA is embedded into the IDE/platform, other 
IDE/platform modules will start to have dependencies on it and we will not be able to easily replace the NetBeans-
provided version with our own (as a library wrapper module).  This would be critical for us if we needed an 
older/newer/patched version of JNA that differs from what the platform provides.
Comment 16 Jaroslav Tulach 2008-02-20 16:18:53 UTC
Re. friend dependencies - that is possible, solves my previous complaint, however does not prevent the pollution of 
platform code with native code, which Tom does not like as well as David and me.

However I have another reason: We proudly differentiate ourselves as being able to run as JNLP application without any 
permissions. Something our competition cannot do. We shall not compromise this with JNA. The original proposal was OK 
in this respect. Just do not enable JNA when creating new platform application. The approach with friend dependencies 
is imho bigger threat. Do we not need to do something special to apisupport or build system?
Comment 17 Jesse Glick 2008-02-20 16:38:51 UTC
To Tom: if you want your app to use a different version of JNA, it should suffice to just include your own lib wrapper
of JNA instead of the platform's version. You only need to ensure that the code name base is the same so dependencies
are satisfied.

I don't think the standard NB module system can run without permissions on JNLP, since it makes quite a number of
privileged calls such as setting the security manager; but anyway if you wanted to prepare a special no-perm version of
NB to run on JNLP then among other changes you would simply omit the native libs from jna.jar, in which case all calls
to Native.loadLibrary would fail and the fallback code in various clients would be triggered, just as it would for an
unsupported OS/arch. Or you could leave in the native libs, in which case running with perms all would work normally,
and without perms you would just get a SecurityException which should trigger the fallback code too.
Comment 18 tomwheeler 2008-02-20 20:34:18 UTC
Jesse: thanks for the info, although maybe I'd have to make sure the version number for my wrapper module matched (or 
possibly exceeded) the one from the platform?  Anyway, so long as I can replace the version in the platform (if I might 
ever need to), then my needs are met. I'd be happy to test that on a nightly build when/if it's implemented.
Comment 19 Jesse Glick 2008-02-20 21:30:07 UTC
Yes, of course the version number for your wrapper would have to satisfy that requested in any dependency in the
platform, most simply by copying the number from the platform's module.
Comment 20 Jaroslav Tulach 2008-02-21 08:25:44 UTC
Nokia used to have an application based on NetBeans that run without any permissions. Is that true Davide?

Re. JNA and JNLP. Someone please verify that if you have JNA the way Jesse wants it - e.g. core/windows requires its 
presence, that you will be able to create a standalone application on such platform and run it in JNLP mode. If not, 
than the proposal is imho not integrable.

I am afraid that the JNLP build will fail due to not packaged files in JNA's NBM. Of course, I may be wrong. Jesse did 
some fixes in JNLP last year, but as far as I know these affect just the "shared JNLP repository" not standalone JNLP 
build.

Only emocional comment: I still do not see the advantage of polluting NetBeans modules with dependency on native code. 
It is one of the biggest strengths of NetBeans that it is 100% pure Java, and this can only compromise that. Better to 
keep the code hidden in one module.
Comment 21 Stanislav Aubrecht 2008-02-21 08:47:46 UTC
i still don't like the idea of core.windows depending directly on some third party library. so how about this solution:
- NativeWindowSystem will move from api.nativeaccess to core.windows as a friend api
- api.nativeaccess will be removed
- NativeWindowSystemImpl and all other code from libs.jna will move to a new module core.nativewindows which will depend
on core.windows and libs.jna. it will have no public api
- libs.jna will be a friend-only library

this should keep everybody happy - there's no new public API and it's possible to get rid of native bindings by removing
core.nativewindows and libs.jna modules
Comment 22 David Simonek 2008-02-21 10:22:15 UTC
Standa's suggestion seems OK to me.

But I must say I still don't understand Jesse's arguments. Jesse you did write things like "silly callback API"...heeh?
It is normal decoupling, adding extra delegation level for greater flexibility, very basic principle of OOP world...

Maybe my view is too limited and narrow, but Jesse what's *wrong* with that extra level? The fact that extra work is
needed in case client would want to use JNA in netbeans module? Yes, but that's so easy - just add method that delegate
to non-trivial JNA related code that you have to write anyway.

Look how the code looks - I really don't feel comfortable when code like this
https://jna.dev.java.net/source/browse/jna/trunk/jnalib/src/com/sun/jna/examples/win32/W32API.java?rev=370&view=markup
https://jna.dev.java.net/source/browse/jna/trunk/jnalib/src/com/sun/jna/examples/win32/Kernel32.java?rev=367&view=markup
is not isolated.

Maybe the problem is how I view JNA - JNA is just a way how to access native code. But that's not enough for usage in
java code directly, you have to write java - native mappings (like shown in code links above). Huge and clumsy code that
copies internal structures of native OS APIs. JNA is not useful, does nothing without these mapping classes. JNA authors
call it "examples" of JNA usage, for me it's more actual "bridge to java". Again, do we want to have this code scattered
and duplicated through NetBeans codebase? Me definitely not. IMHO mapping classes should be isolated and hidden.

Standa's last suggestion isolates mapping classes into core.nativeaccess module (Standa wrote core.nativewindows but i
think it's a typo) so I'm satisfied. I still would prefer initial design, but I can live with that.
Comment 23 Jesse Glick 2008-02-21 16:15:59 UTC
"I am afraid that the JNLP build will fail due to not packaged files in JNA's NBM" - if you do nothing special, that NBM
should contain only jna.jar (and the usual config/Modules/*.xml). If you write a special jnlp target in the module's
build script (applicable only to the shared repo of course) then you can choose to instead strip the native libs from
the JAR and create separate <resource> sections for each OS pointing to separate JARs with one native lib each, as
documented on the JNA website, but this is quite optional - would just save a very small amount of download bandwidth.

I don't see how we would be "polluting" anything more than you are already. (Let's ignore the existing native launcher,
extbrowser.dll, and random calls to Runtime.exec for the moment!) You want to run native code rather than pure Java for
window system functionality whenever possible. Invoking the native lib through callbacks just obscures the fact that you
are normally making native calls.

To Dafe: sure the code can be ugly, if the native API is complex. That's true of any API, it's not a problem with JNA.
If the native API is straightforward, JNA usage is simple:

    public static void main(String[] args) {
        byte[] buf = new byte[16];
        UUID.INSTANCE.uuid_generate(buf);
        System.out.printf("%032X\n", new BigInteger(1, buf));
    }
    private interface UUID extends Library {
        UUID INSTANCE = (UUID) Native.loadLibrary("uuid", UUID.class);
        void uuid_generate(byte[/*16*/]/*uuid_t*/ out);
    }

Moving the code to a different module doesn't make it any simpler.

Anyway it seems I am outnumbered so let's go with Standa's latest proposal; at least we are not committing to any new
public APIs.
Comment 24 Stanislav Aubrecht 2008-02-21 17:16:26 UTC
ok, if there are no more objections, i'll add JNA library and new windows effects (my latest proposal) into main
repository on friday morning
Comment 25 Stanislav Aubrecht 2008-02-22 16:54:38 UTC
integrated in trunk

http://hg.netbeans.org./main/rev/882b48e4e1f1
Comment 26 Stanislav Aubrecht 2008-03-14 15:59:52 UTC
closing