Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

native methods - java.lang.UnsatisfiedLinkError

305 views
Skip to first unread message

David Komanek

unread,
Oct 25, 2002, 6:02:57 AM10/25/02
to
Hi all,

I have problem with native functions in DLLs called from Java.
Probably there is something more general I am missing and probably I
don't understand the mechanism completely. Bellow is my example code.
It calls the function zlibVersion() from system library zlib.dll
(WINNT\SYSTEM32\zlib.dll, Win2k). I suppose this library was compiled
by MS Visual C++, but not sure. I tried similar things for various
libraries and functions with the same error

java.lang.UnsatisfiedLinkError

while running the class (it is not compile time error, only runtime
exception). When the library is not found, it throws another
expection, so I can exclude this roblem. The problem is the function
is not found in the loaded library, although it is in its export
table.

Do you have some idea how to solve this ? JDK 1.4.1, problem is the
same with both JBuilder and java.exe compiler from SUN.

Thanks in advance,

David Komanek


Example code:

package cz.komanek.dlltest;
import java.lang.*;

public class Test {
static {
System.loadLibrary("zlib");
}
public Test() {
System.out.println("" + zlibVersion());
}
public static void main(String[] args) {
Test test = new Test();
}
public static native String zlibVersion();
}


Output:

java.lang.UnsatisfiedLinkError: zlibVersion
at cz.komanek.dlltest.cygwinDllKrbIV.zlibVersion(Native Method)
at cz.komanek.dlltest.cygwinDllKrbIV.<init>(cygwinDllKrbIV.java:22)
at cz.komanek.dlltest.cygwinDllKrbIV.main(cygwinDllKrbIV.java:26)
Exception in thread "main"


zlib.dll interface:

File type: WINDOWS EXECUTABLE

File Header:
Machine: 0x014C (Intel x86)
Number of Sections: 5
Time Date Stamp: 0x3A268963 (30.11. 2000 19:07:47)
Pointer to Symbol Table: 0x00000000
Number of Symbols: 0
Size of Optional Header: 0x00E0 (224)
Characteristics: 0x210E
File is executable.
Line numbers stripped from file.
Local symbols stripped from file.
32 bit word machine.
File is a DLL.

Optional Header:
Magic: 0x010B
Linker Version: 6.00
Size of Code: 0x00008000 (32768)
Size of Initialized Data: 0x00006000 (24576)
Size of Uninitialized Data: 0x00000000 (0)
Adress of Entry Point: 0x00001000
Base of Code: 0x00001000
Base of Data: 0x00009000
Image Base: 0x5A000000
Section Align: 0x00001000
File Align: 0x00001000
Operating System Version: 4.00
Image Version: 1.01
Subsystem Version: 4.00
Size of Image: 0x0000F000 (61440)
Size of Headers: 0x00001000 (4096)
Checksum: 0x00000000
Subsystem: 0x0002 (Windows GUI subsytem)
DLL Characteristics: 0x0000
Size of Stack Reserve: 0x00100000 (1048576)
Size of Stack Commit: 0x00001000 (4096)
Size of Heap Reserve: 0x00100000 (1048576)
Size of Heap Commit: 0x00001000 (4096)
Loader Flags: 0x00000000
Number of Rva and Sizes: 16

Data Directory:
Export directory: VA: 0x0000A670 Size: 0x000005D5
(1493)
Import directory: VA: 0x0000A4C0 Size: 0x00000028
(40)
Resource directory: VA: 0x0000D000 Size: 0x000003E0
(992)
Exception directory: VA: 0 Size: 0
Security directory: VA: 0 Size: 0
Base relocation table: VA: 0x0000E000 Size: 0x000002A4
(676)
Debug directory: VA: 0 Size: 0
Architecture-specific data: VA: 0 Size: 0
RVA of global pointer: VA: 0 Size: 0
Thread local storage directory: VA: 0 Size: 0
Load configuration directory: VA: 0 Size: 0
Bound import directory: VA: 0 Size: 0
Import address table: VA: 0x00009000 Size: 0x00000068
(104)
Delay load import descriptors: VA: 0 Size: 0
COM run-time descriptor: VA: 0 Size: 0
(unknown directory entry): VA: 0 Size: 0

Export Table:
Name: ZLIB.dll
Time Date Stamp: 0x3A26893D (30.11. 2000 19:07:09)
Version: 0.00
Ordinal Base: 1
Number of Functions: 84
Number of Names: 61

Ordinal Entry Point Name
1 0x00001048 adler32
2 0x000011E4 compress
39 0x00001163 compress2
3 0x00001204 crc32
4 0x00002352 deflate
5 0x00002682 deflateCopy
6 0x000025F9 deflateEnd
7 0x00001F79 deflateInit2_
8 0x00001F59 deflateInit_
9 0x000022A4 deflateParams
10 0x00002236 deflateReset
11 0x00002157 deflateSetDictionary
38 0x000011FE get_crc_table
12 0x00001DC9 gzclose
13 0x0000152F gzdopen
34 0x00001D71 gzeof
14 0x00001E2F gzerror
15 0x00001B04 gzflush
30 0x00001986 gzgetc
41 0x000019A9 gzgets
16 0x0000131F gzopen
28 0x00001A76 gzprintf
29 0x00001AC0 gzputc
40 0x00001AE9 gzputs
17 0x000017B5 gzread
32 0x00001D03 gzrewind
31 0x00001BD9 gzseek
35 0x00001567 gzsetparams
33 0x00001D61 gztell
18 0x000019F2 gzwrite
19 0x00004CE0 inflate
20 0x00004BAA inflateEnd
21 0x00004BE6 inflateInit2_
22 0x00004CCA inflateInit_
23 0x00004B6B inflateReset
24 0x0000503F inflateSetDictionary
25 0x000050B4 inflateSync
37 0x00005163 inflateSyncPoint
26 0x00001EDF uncompress
62 0x000076D9 unzClose
72 0x00008030 unzCloseCurrentFile
64 0x0000772B unzGetCurrentFileInfo
73 0x0000809A unzGetGlobalComment
63 0x0000770A unzGetGlobalInfo
76 0x00007FB7 unzGetLocalExtrafield
65 0x00007A64 unzGoToFirstFile
66 0x00007AA1 unzGoToNextFile
75 0x00007AFA unzLocateFile
61 0x00007389 unzOpen
67 0x00007B89 unzOpenCurrentFile
68 0x00007E11 unzReadCurrentFile
74 0x00007313 unzStringFileNameCompare
71 0x00007F96 unzeof
70 0x00007F7C unztell
36 0x00004B37 zError
84 0x00007184 zipClose
83 0x00006F53 zipCloseFileInZip
80 0x0000697D zipOpen
81 0x000069FA zipOpenNewFileInZip
82 0x00006E75 zipWriteInFileInZip
27 0x00004B31 zlibVersion

Import Table:
MSVCRT.dll
Import Adress Table: 0x00009000
Import Name Table: 0x0000A4E8
Time Date Stamp: 0x00000000
Index of first forwarder reference: 0x00000000

0x0000A550 612 ftell
0x0000A56C 599 fopen
0x0000A574 200 _errno
0x0000A57E 698 strcpy
0x0000A588 702 strlen
0x0000A592 657 malloc
0x0000A59C 690 sprintf
0x0000A5A6 614 fwrite
0x0000A5B0 605 fread
0x0000A5B8 588 fclose
0x0000A5C2 606 free
0x0000A5CA 663 memcpy
0x0000A558 600 fprintf
0x0000A562 215 _fdopen
0x0000A5EA 610 fseek
0x0000A5F2 665 memset
0x0000A5FC 682 rewind
0x0000A606 601 fputc
0x0000A60E 694 strcat
0x0000A618 576 calloc
0x0000A622 696 strcmp
0x0000A62C 271 _initterm
0x0000A638 157 _adjust_fdiv
0x0000A5D4 732 vsprintf
0x0000A5E0 591 fflush

Section Table:
Section Header #1
Name: .text
Virtual Size: 0x00007218 (29208)
Virtual Address: 0x00001000
Size of Raw Data: 0x00008000 (32768)
File Pointer to Raw Data: 0x00001000
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0x60000020
Section contains code.
Section is executable.
Section is readable.

Section Header #2
Name: .rdata
Virtual Size: 0x00001C45 (7237)
Virtual Address: 0x00009000
Size of Raw Data: 0x00002000 (8192)
File Pointer to Raw Data: 0x00009000
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0x40000040
Section contains initialized data.
Section is readable.

Section Header #3
Name: .data
Virtual Size: 0x000011F8 (4600)
Virtual Address: 0x0000B000
Size of Raw Data: 0x00002000 (8192)
File Pointer to Raw Data: 0x0000B000
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xC0000040
Section contains initialized data.
Section is readable.
Section is writeable.

Section Header #4
Name: .rsrc
Virtual Size: 0x000003E0 (992)
Virtual Address: 0x0000D000
Size of Raw Data: 0x00001000 (4096)
File Pointer to Raw Data: 0x0000D000
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0x40000040
Section contains initialized data.
Section is readable.

Section Header #5
Name: .reloc
Virtual Size: 0x0000030A (778)
Virtual Address: 0x0000E000
Size of Raw Data: 0x00001000 (4096)
File Pointer to Raw Data: 0x0000E000
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0x42000040
Section contains initialized data.
Section can be discarded.
Section is readable.

Thomas Kellerer

unread,
Oct 25, 2002, 7:06:19 AM10/25/02
to
kom...@natur.cuni.cz
I'm not an expert with JNI, but to my knowledge you cannot just call any
function in a dll. The dll needs to be specifically compiled to be used by
Java.

Especially with your code (I think) the JVM is expecting a function called:

cz_komanek_dlltest_zlibVersion()

I'm not sure about the underscores, but the point is, that the full class is
expected somehow in the interface declaration of the DLL.

Thomas

Gordon Beaton

unread,
Oct 25, 2002, 7:14:12 AM10/25/02
to
On 25 Oct 2002 03:02:57 -0700, David Komanek wrote:
> I have problem with native functions in DLLs called from Java.
> Probably there is something more general I am missing and probably I
> don't understand the mechanism completely. Bellow is my example
> code. It calls the function zlibVersion() from system library
> zlib.dll (WINNT\SYSTEM32\zlib.dll, Win2k).

You can't call arbitrary native functions from Java. Write a set of
wrappers for the zlib functions you need, compile that into a
JNI-compatible library, and use that instead.

/gordon

--
[ do not send me private copies of your followups ]
g o r d o n . b e a t o n @ e r i c s s o n . c o m

Joerg Gippert

unread,
Oct 25, 2002, 8:47:57 AM10/25/02
to

"David Komanek" <kom...@natur.cuni.cz> schrieb im Newsbeitrag
news:e54ab944.0210...@posting.google.com...
> Hi all,

Hi David!

> I have problem with native functions in DLLs called from Java.
> Probably there is something more general I am missing and
probably I
> don't understand the mechanism completely. Bellow is my example
code.
> It calls the function zlibVersion() from system library
zlib.dll
> (WINNT\SYSTEM32\zlib.dll, Win2k). I suppose this library was
compiled
> by MS Visual C++, but not sure. I tried similar things for
various
> libraries and functions with the same error
>
> java.lang.UnsatisfiedLinkError
>
> while running the class (it is not compile time error, only
runtime
> exception). When the library is not found, it throws another
> expection, so I can exclude this roblem. The problem is the
function
> is not found in the loaded library, although it is in its
export
> table.
>
> Do you have some idea how to solve this ? JDK 1.4.1, problem is
the
> same with both JBuilder and java.exe compiler from SUN.

[snip]


You get an UnsatisfiedLinkError, if the DLL is not found OR the
function you´re calling is not found.
You cannot call any DLL function from Java. Your DLL must be
compiled for use with Java. First you declare a native funtion in
your Java file. Then, you can either create a C/C++ header file
from your Java code using " javah myJavaCode.java" or write your
own header file (use javah, it´s easier). A typical C++ function
header being called by Java looks like this for example:

JNIEXPORT jstring JNICALL
Java_MyJavaClassName_FunctionNameDeclaredInHJavaFile
(JNIEnv *env, jobject, jobjectArray arr, jstring llFilename)
{
//your function code
}

To be clear: You must have both - the Java and DLL source code.
In order to call a Windows function in a Windows DLL, you must
write your own Java compliant DLL which in turn calls the Windows
DLL function. There´s no way to call a Windows DLL function
directly. Java comes with with a jni.h header file which is
necessary to work with Java C++ types which you can see in the
argument list of the function above (jstring for example is the
C++/C version of a Java String object). If your DLL is not
compiled with this jni.h icluded (which applies to most DLL´s and
especially to Windows DLL´s), you can´t work with them in Java.

HTH.

Regards,
Joerg


Joerg Gippert

unread,
Oct 25, 2002, 11:32:08 AM10/25/02
to

"TGOS" <tg...@invalid.invalid> schrieb im Newsbeitrag
news:4rhiru0hqtq58vldv...@4ax.com...
>
> On Fri, 25 Oct 2002 14:47:57 +0200 "Joerg Gippert"
> <joerg....@arcor.de> wrote in comp.lang.java.programmer:
>
> > There愀 no way to call a Windows DLL function
> > directly.
>
> Well, there is one way.
> There is a commercial Windows JNI API that allows you to call
every DLL
> function of every existing DLL. The JNI code will load the DLL
> dynamically and then allows you to prepare parameters via
methods and
> then it will call the DLL function (which you provide via name
as
> String). However, it's slow like hell (only pays off for
functions that
> don't have to be called very often in your code) and it's
expensive.

Intresting, I didn愒 know such a thing is around. But what I
meant to say is, that you can愒 write a native method that
directly calls, let愀 say kernel32.dll and execute a function
there. I惴 sure, that this commercial API just uses a wrapper DLL
which passes the values from Java into the original DLL. Sure, a
lot of to write wrapper functions for all possible Windows API
functions. Please correct me, if I惴 wrong. I惴 still eager to
learn :)

Regards,
Joerg


David Komanek

unread,
Oct 29, 2002, 3:05:25 AM10/29/02
to
Hi all,

thank you very much. With your help I now understand that to the
native DLL function I need another DLL as an wrapper and this wrapper
should be written in C/C++. I tried it and voila, I can link my test
program now. But still have big problems:

I have now a small test program which call wrapper function written in
Cygwin gcc. It only sends some string to "stdout" saying something
like "I was called" and call the apporpriate zlib.dll function it
wraps, then it returns the return code of this wrapped function to
Java program.
Java program calls this wrapper function from consructor and sends the
returned value to "System.out". It also prints out something like
"Again in java code" message.

Although I can admit, there should be some conversion mechanics
between different data representation (i.e. instead of string value
java gets something like name of the string object as an value ....)
it seems to be very strange for me to see that there is problem with
sending text to console via System.out.println()
- if I run my example in JBuilder6, it works fine
- the same results with java form cygwin environment
- if I run my example code from Win2k command line, it writes out
right the text generated in dll wrapper function but not text
generated in the java code section. It turns out to make the problem
more general: if I load the library, I have no chance to see the
output of System.out.println()

I tested it vith jre 1.3.0, 1.3.1 and 1.4.1beta and it is still the
same problem.

Is it a known problem ? Does it mean, I am doing something wrong or is
it real compatibility problem ? How to deal thing JAVA has no API for
?

One solution could be to use a call to the external executable instead
of wrappering DLL and to deal with its return code in pure java
application, or to communicate with the standalone binary through
redirected input and output. Does this idea some support in Java API ?

Many thanks in advance,

David Komanek

JAVA CODE:
=============
package cz.komanek.dlltest;
import java.lang.*;
import java.io.*;
import java.util.*;

public class cygwinDllKrbIV {
static {
System.loadLibrary("cygwinDllTest");
}
public cygwinDllKrbIV() {
Integer number = new Integer(0);
System.out.println("TEST");
System.out.println("version: " + getzlibVersion());
System.out.println("errors: " + getgzerror(System.err , number));
System.out.println("parameter: " + number);
// System.out.flush(); //even this does not help me !
}
public void testOutput() {
System.out.println("POKUS - test");


}
public static void main(String[] args) {

cygwinDllKrbIV cygwinDllKrbIV1 = new cygwinDllKrbIV();
// cygwinDllKrbIV1.testOutput(); //throws exception if some DDL is
loaded !
}
public static final native int getzlibVersion();
public static final native String getgzerror(Object o, Integer i);
}

C-WRAPPER DLL CODE:
=====================
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "cygwinDllTest.h"

static char *tmpstr = "Hello !";

JNIEXPORT jint JNICALL
Java_cz_komanek_dlltest_cygwinDllKrbIV_getzlibVersion
(JNIEnv *a, jclass b) {
return((jint)zlibVersion());
}

JNIEXPORT jstring JNICALL
Java_cz_komanek_dlltest_cygwinDllKrbIV_getgzerror
(JNIEnv *a, jclass b, jobject c, jobject d) {
fprintf(stderr,"%d\n",1234);
fprintf(stderr,"%s\n","dll function entered");
fflush(stderr); //Needed to see some output !
//return(""); //throws exception in Java code !
//return((jstring)tmpstr); //throws exception in Java code !
return((jstring)gzerror(c,d));
}

HEADER FILE FOR WRAPPER:
===========================
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cz_komanek_dlltest_cygwinDllKrbIV */

#ifndef _Included_cz_komanek_dlltest_cygwinDllKrbIV
#define _Included_cz_komanek_dlltest_cygwinDllKrbIV
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cz_komanek_dlltest_cygwinDllKrbIV
* Method: getzlibVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_cz_komanek_dlltest_cygwinDllKrbIV_getzlibVersion
(JNIEnv *, jclass);

/*
* Class: cz_komanek_dlltest_cygwinDllKrbIV
* Method: getgzerror
* Signature: (Ljava/lang/Object;Ljava/lang/Integer;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_cz_komanek_dlltest_cygwinDllKrbIV_getgzerror
(JNIEnv *, jclass, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif

Gordon Beaton

unread,
Oct 29, 2002, 4:08:58 AM10/29/02
to
On 29 Oct 2002 00:05:25 -0800, David Komanek wrote:
> I have now a small test program which call wrapper function written
> in Cygwin gcc. It only sends some string to "stdout" saying
> something like "I was called" and call the apporpriate zlib.dll
> function it wraps, then it returns the return code of this wrapped
> function to Java program.
>
> Java program calls this wrapper function from consructor and sends
> the returned value to "System.out". It also prints out something
> like "Again in java code" message.
>
> Although I can admit, there should be some conversion mechanics
> between different data representation (i.e. instead of string value
> java gets something like name of the string object as an value ....)

That is an understatement!

When the caller (rather, the JVM) expects your method to return a
jstring, you can't just return an arbitrary value with a explicit
(jstring) typecast put there to silence the compiler.

If you don't have anything to return, declare the methods void
instead. Or use NewStringUTF("some string"); to make a valid jstring.

It is anybody's guess what the results of your current return value
are. I can imagine that you manage to corrupt some internal JVM
structures.

0 new messages