Using JNA with IBM J9 JVM - java

The first difficulty in using JNA with J9 is that the J9 JVM does not include the java.awt package and the Native class imports a few classes from this package. This is easily overcome by downloading the JNA source, ripping out these imports and their dependent methods (which I am not using anyway), and building a new JNA jar.
Here is a simple test program:
public class TestJni {
public static void main(String[] args) {
CLibrary instance = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
instance.printf("Hello, World\n", new Object[] {});
}
// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
void printf(String format, Object[] args);
}
}
After correcting the java.awt problem, I receive the error:
Caused by: java.lang.UnsatisfiedLinkError: C:\DOCUME~1\TSO0112\LOCALS~1\Temp\jna72681.dll (Incompatible JNI version (not 1.1, 1.2 or 1.4))
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:973)
at java.lang.System.load(System.java:459)
at com.sun.jna.Native.loadNativeLibraryFromJar(Native.java:696)
at com.sun.jna.Native.loadNativeLibrary(Native.java:620)
at com.sun.jna.Native.<clinit>(Native.java:104)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:187)
at TestJni.main(TestJni.java:8)
What does it mean by "Incompatible JNI version"? Has anybody out there got J9 to play nice with JNA?
UPDATE: I think JNA is suppressing the following NoClassDefFoundError on trying to load the java.nio.Buffer class because J9 apparently does not have the NIO package included:
JNA: Problems loading core IDs: java.nio.Buffer
Exception in thread "main" java.lang.NoClassDefFoundError: java.nio.Buffer
at java.lang.ClassLoader.loadLibraryWithPath(Native Method)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:965)
at java.lang.System.load(System.java:459)
at TestJni.main(TestJni.java:8)

I have been working with JNA on j9 for a couple of months now. I have had a few small niggles here and there but things mostly seem working fine.
First - The latest versions of JNA(3.2.7) seem to import awt. I am using 3.2.4 and the awt imports are commented out. I think that will work out of the box for you.
Second - THe version of J9 i am working with is for WinCE and it is a JVM for java 1.4. Latest JNA though is built off of java 1.5. So you might want to check which version of java your version of j9 is built on. JNA 3.2.4 is compatible with java 1.4 I believe.

You can also simply provide your own stub implementations of the java.nio/java.awt stuff and simply avoid using those features (mainly direct buffer stuff and obtaining a handle to a native window).

Related

Getting JNA to work under Java 1.4

For reasons not germane to this question, I'm stuck with an old RHEL/CentOS 5 system with Java 1.4 (java version "1.4.2" gij (GNU libgcj) version 4.1.2 20080704 (Red Hat 4.1.2-44)). According to the JNA documentation, it's supposed to work. However the example provided is off to a rocky start since it uses a feature of Java 1.5, namely varargs (void printf(String format, Object... args)). So I figured I'd try with a simpler C library call, strerror.
package ca...cl_client;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class MainJNA {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
Pointer strerror(int errno);
}
public static void main(String[] args) {
System.out.println("Hello, World");
System.out.println("err 22 : " + CLibrary.INSTANCE.strerror(22).getString(0)); //EINVAL
}
}
So I deploy jna-master.zip locally and hook it up:
$ sudo -- ln -s /home/user/Downloads/Java/jna-master/dist/jna.jar /usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre/lib/jna.jar
$ export CLASS_PATH=.:/home/user/Downloads/Java/jna-master/dist/jna.jar
This compiles fine:
$ cd ~/Java
$ javac ./ca/gc/drdc_rddc/linux/utilinux/cl_client/MainJNA.java
But it won't run:
$ java -cp $CLASS_PATH ca...cl_client.MainJNA
Hello, World
Exception in thread "main" java.lang.ClassFormatError: com.sun.jna.Library (unrecognized class file version)
at java.lang.VMClassLoader.defineClass(libgcj.so.7rh)
at java.lang.ClassLoader.defineClass(libgcj.so.7rh)
at java.security.SecureClassLoader.defineClass(libgcj.so.7rh)
at java.net.URLClassLoader.findClass(libgcj.so.7rh)
at java.lang.ClassLoader.loadClass(libgcj.so.7rh)
at java.lang.ClassLoader.loadClass(libgcj.so.7rh)
at java.lang.VMClassLoader.defineClass(libgcj.so.7rh)
at java.lang.ClassLoader.defineClass(libgcj.so.7rh)
at java.security.SecureClassLoader.defineClass(libgcj.so.7rh)
at java.net.URLClassLoader.findClass(libgcj.so.7rh)
at java.lang.ClassLoader.loadClass(libgcj.so.7rh)
at java.lang.ClassLoader.loadClass(libgcj.so.7rh)
at ca...cl_client.MainJNA.main(MainJNA.java:19)
Compiling with javac -cp $CLASS_PATH ... makes no difference.
I've tried this on both a 32-bit system and a 64-bit system (each RHEL 5.3), the error is the same.
What am I doing wrong?
1.)
I checked the official JNA library classes with the following result:
JNA 4.0.0 -> compiled with 1.6
JNA 3.5.0 -> compiled with 1.4
JNA 3.5.2 -> compiled with 1.4
And when looking exactly for that you'll find it, too:
Switch to 1.6 (In the release notes for version 4.0). Additionally there is an issue #109. So your last working version would be 3.5.2.
2.) Regarding the exotic java version you may read here. Some quotes to give you some ideas:
"gij hasn't passed the Sun compatability test, and should be
considered a separate platform for building, testing etc."
"GCJ is not equivalent to Sun's JDK or JRE, so you may find that
certain things you need aren't included in the API.
"gij is very ancient, and while I don't have references I doubt it's
reliable enough to support commercial applications."
Getting to run JNA correctly is sometimes tricky enough in a sun/oracle/open jdk - so this won't be a trivial task...

ACM Library simple example not working with jdk 1.7.0_79

Hi All java Experts!
When I tried a little example of acm library
import acm.program.*;
class prog extends ConsoleProgram {
public void run() {
int number = readInt("?");
println("You entered: " number);
}
}
It compiled successfully.
I used commandline like this:
javac -cp acm.jar; main.java
java -cp acm.jar; prog
But I got this error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: acm.util.DOSCommandLi
ne.getLine()Ljava/lang/String;
at acm.util.DOSCommandLine.getLine(Native Method)
at acm.util.DOSCommandLine.getCommandLine(JTFTools.java:1627)
at acm.util.JTFTools.getCommandLine(JTFTools.java:439)
at acm.util.JTFTools.getMainClass(JTFTools.java:464)
at acm.program.Program.main(Program.java:1320)
What does it mean... I think the JDK version problem.... however I am using JDK 'jdk1.7.0_79'
In my opinion It is throwing exception only for this JDK version. Request to try you and give feedback.
Thanks...
Solved!
It doesn't require any native library...
What I had to do was to Use main entry as:
public static void main(String[] args) {
new prog().start(args);
}
Adding after 'run' method it works now. Note: this line 'new prog().start(args);'
This solution found here:
http://www.dreamincode.net/forums/topic/240789-acmjar-package-problem-class-wasnt-find-in-project/
Thanks Choppy
But it took me considerable time Hushhhhh.....
UnsatisfiedLinkError at Native Method means that there is no native library (for windows it would be dll) loaded which could be called for your acm.util.DOSCommandLine.getLine() method.
With your library there should be native packages, which will contain native libraries for your system architecture. You have to put one of these into your classpath folder.

Loading native libraries in java

I have an eclipse project with two classes. The class "SomeClass1" has a native method:
SomeClass1
public class SomeClass1 {
static {
System.loadLibrary("libname"); // Load the native library.
}
public native void some_method(); // implemented in the library
// .... other non methods ....
}
The other class "SomeClass2" uses the native method of "SomeClass1". Like:
SomeClass2
public class SomeClass2{
public static void main(String[] args) {
SomeClass1 s = new SomeClass1();
s.some_method();
}
// ....other methods....
}
However when it calls that method it throws an error like this:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no libname in java.library.path
....
at java.lang.System.loadLibrary(Unknown Source)
at x.x.x.SomeClass1.<clinit>(SomeClass1.java:128)
at SomeClass2.main(SomeClass2.java:10)
I think the error has something to do with java not knowing where to look for the native library.
Question1
When I use: -Djava.library.path="C:\Users.....\libfolder\" as run argument in eclipse and print the value of: System.getProperty("java.library.path"); I see alot of directories printed but not the directory that I specified in the argument. What am I doing wrong?
Question2
When I do: System.loadLibrary("name"); do I need to call the library "name.so" or "libname.so"?
Question3
If the library would be found but was a 64 bit library while the platform it is loaded on is 32 bit, would it also give a unsatisfiedLinkError or would a different error be given?
Question4
Can I specify the path to the library relative to the projects folder or relative to the file in which the library is loaded?
Hope you are able to answer (some of) my questions.
Grtz Stefan
Question 1:
You should not add this as a run argument, but as a VM argument. It's not an argument for your program, but for the JVM.
Question 2:
(Also #IanRoberts ) : The System.loadLibrary(name) call will automatically derive the name of the actual library from the given name. That means that it will append ".dll" on windows, and use "lib" + name + ".so" on linux. Otherwise, loading a native lib would not be possible in a platform-independent way!
Question 3:
In general, the UnsatsfiedLinkError is distressingly common. It's in fact true to say: The UnsatisfiedLinkError does not tell you more than "Something is wrong". You can only hope for the actual error message to be more descriptive, and this would (fortunately) be the case if you had a 32/64bit mismatch - at least on windows:
Trying to load a 32bit lib on a 64bit system will cause the message: "Can't load IA 32-bit .dll on a AMD 64-bit platform"
Trying to load a 64bit lib on a 32bit system will cause the message: "... is not a valid Win32 application"
(I'm not sure about the message for other operating systems, though, but your message indicates that the library is just not found, and not that there's a problem with the library itself)
(Question 4: I'm rather sure that this is possible, but not absolutely sure (and can't try it out) at the moment. In general, the library must be in a path that is visible via the PATH environment variable, or via the java.library.path. In doubt, it should always work then the native libs are in the same directory as where you are starting your program from)

Statically Linking a GCJ Application on Ubuntu Natty

I'm trying to statically link a GCJ application and it looks like theres some misconfiguration somewhere. I'm just using the standard gcj installation on natty and I have both libgcj11 and libgcj11-dev installed.
My test application is:
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
I do:
gcj -static-libgcj --main=HelloWorldApp HelloWorldApp.java
then i get the following error
/usr/bin/ld: cannot find -lgcj
collect2: ld returned 1 exit status
Anyone know how to fix this?
Distros generally do not ship libgcj.a. Static linking does not work extremely well with gcj, anyway, mostly because not all of the class dependencies can be found -- compiled-in resources and also the use of reflection in the core library cause things to go missing at link time, unless you take special care to link them in by hand.

SWT + Maven + Eclipse = java.lang.UnsatisfiedLinkError: no swt-carbon-3346 or swt-carbon in swt.library.path

I am trying to get a hello world SWT application going:
public static void main(String args[]) throws IOException{
Display display = new Display ();
Shell shell = new Shell(display);
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
But I keep getting the following exception. I have the macosx version of org.eclipse.swt.carbon being used with eclipse/maven. Has anyone seen this before?
Exception in thread "main" java.lang.UnsatisfiedLinkError: no swt-carbon-3346 or swt-carbon in swt.library.path, java.library.path or the jar file
at org.eclipse.swt.internal.Library.loadLibrary(Library.java:219)
at org.eclipse.swt.internal.Library.loadLibrary(Library.java:151)
at org.eclipse.swt.internal.C.<clinit>(C.java:21)
at org.eclipse.swt.widgets.Display.createDisplay(Display.java:943)
at org.eclipse.swt.widgets.Display.create(Display.java:937)
at org.eclipse.swt.graphics.Device.<init>(Device.java:119)
at org.eclipse.swt.widgets.Display.<init>(Display.java:749)
at org.eclipse.swt.widgets.Display.<init>(Display.java:740)
at com.wuntee.aat.command.adb.LogCat.main(LogCat.java:30)
SWT is implemented using native UI libraries - in this case, the Mac Carbon libraries - and requires some JNI code to marshal the SWT calls to the native Carbon calls. Loading JNI libraries is a little bit different than normal classloading (the dynamic libraries must first be loaded with System#loadLibrary).
First, if you're on a 64 bit machine, make sure that you're passing the -d32 argument to the JRE. (ie, java -d32 MyTestClass). The Carbon SWT libraries are 32 bit only and will not load on a 64 bit runtime.
By default, SWT tries to load the .jnilib dynamic libraries from a JAR file in your classpath - the library libswt-carbon-3346.jnilib should be in your org.eclipse.swt.carbon.macosx... JAR. SWT will try to unzip this jnilib from your JAR into a temporary location and load that.
If it can't do this for whatever reason (java.io.tmpdir isn't writable, for example) then this will fail. To work around this, you should extract libswt-carbon-3346.jnilib from the org.eclipse.swt.carbon.macosx JAR and follow the instructions that the exception provided. (For example, set swt.library.path to the location of that jnilib.)
Unrelated to your actual question: you're using SWT 3.3. A lot of changes have been made since then, including the (likely preferable) Cocoa support. Upgrading to the newest SWT libraries in the newest Eclipse may be very helpful.

Categories

Resources