0x6B6F77616C74
0x6B6F77616C74

Reputation: 2629

Using winapi in java application

I've tried to invoke the MessageBoxA function in a JAVA code. What is wrong with the following approaches, so that my program throws a lot of errors?

package loading.libraries;

public class User32
{
    //first case:public native int MessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
    //second: public native int MessageBoxA(int hWnd,String lpText,String lpCaption,int uType);
    static  
    {
        System.loadLibrary("User32");
    }        

}

package loading.libraries;

public class LoadingLibraries 
{
    public static void main(String[] args) 
    {
        User32 hwapi = new User32();

        hwapi.MessageBoxA(0,"Hello","World",0);               
    }
}

1-st:

run: Exception in thread "main" java.lang.ClassFormatError: Code attribute in native or abstract methods in class file loading/libraries/MessageBox at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:791) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at loading.libraries.LoadingLibraries.main(LoadingLibraries.java:8) Java Result: 1 BUILD SUCCESSFUL (total time: 2 seconds)

2-nd:

run: Exception in thread "main" java.lang.UnsatisfiedLinkError: loading.libraries.User32.MessageBoxA(ILjava/lang/String;Ljava/lang/String;I)I at loading.libraries.User32.MessageBoxA(Native Method) at loading.libraries.LoadingLibraries.main(LoadingLibraries.java:10) Java Result: 1 BUILD SUCCESSFUL (total time: 0 seconds)

Upvotes: 1

Views: 2956

Answers (3)

Boris Brodski
Boris Brodski

Reputation: 8695

You are using Java JNI. JNI is unable to just call any DLL methods, but only method designed to be called from JVM. Your C method signature within DLL should match your Java method signature as defined in JNI specification.

For example this C function

include "jni.h"

JNIEXPORT jobject JNICALL Java_net_sf_sevenzipjbinding_SevenZip_nativeOpenArchive(JNIEnv * env,
     jclass thiz, jstring formatName, jobject inStream,
     jobject archiveOpenCallbackImpl) { ... }

can be called from Java using following native method declaration:

package net.sf.sevenzipjbinding;

class public class SevenZip {
    private static native ISevenZipInArchive nativeOpenArchive(String formatName, IInStream inStream,
        IArchiveOpenCallback archiveOpenCallback) throws SevenZipException;
    ...
}

As you can see, the exported name in DLL should match java package, class name and method name. The function signature should correspond to the java signature using types defined in jni.h

Example comes from https://github.com/borisbrodski/sevenzipjbinding/

Upvotes: 2

Jesper
Jesper

Reputation: 206776

Using JNI to call native code is not as simple as what you are trying. The functions in the DLL that you are calling must conform to a certain interface, and arbitrary functions in for example Windows User32.dll do not conform to the format that JNI expects.

You can write a wrapper DLL, which means you write some code in C using the JNI API that you can call from Java.

Another approach is to use JNA, which is easier to use than JNI, and which allows you to call functions in an arbitrary DLL without the need to write native code yourself.

Upvotes: 4

user489041
user489041

Reputation: 28294

You need to create a wrapper that will call those functions in the User32 library. Don't call them directly. Take a look at this tutorial http://www.ibm.com/developerworks/java/tutorials/j-jni/.

There are more steps involved then simply loading the library and called the function. Also must note that if you do this, you remove one of the best things of Java. Being able to write once run anywhere. You will be tethered to Windows. If this isnt a problem for you, then no big deal. Are you sure this isnt something you can't do from Java directly. JNI should really be a last resort.

Also, from my experience with JNI, it can lead to unstable applications if not used carefully.

Upvotes: 3

Related Questions