java-native-access / jna

Java Native Access
Other
8.54k stars 1.68k forks source link

$WNDCLASSEX NoSuchFieldError: DEFAULT #765

Closed agaertner closed 7 years ago

agaertner commented 7 years ago

jna-4.3.0.jar, jna-platform-4.3.0.jar Windows 10 The issue only occurs after building my projects and running it, but doesn't occur when testing the single class inside an emulator like BlueJ. The part of the code in which the error occurs: (The MsnMessagePump is a nested class. The msnWndHandle is a synchronied new Object().

/**
     * The runnable MsnMessagePump class handles the messages normally received by the MSN messenger.
     * @throws UnsatisfiedLinkError
     */
    public class MsnMessagePump implements Runnable {
        public void run() { 
            synchronized(msnWndHandle) {
                WNDCLASSEX msnWndClass = new WNDCLASSEX();
                msnWndClass.lpszClassName = lpClassName;
                msnWndClass.lpfnWndProc = WNDPROC;
                if (lib.RegisterClassEx(msnWndClass).intValue() > 0) {
                    // Create a native window
                    HWND hMsnWnd = lib.CreateWindowEx(0, lpClassName, "", 0,
                                0, 0, 0, 0, null, null, null, null);
                    // Register the callback
                    try {
                        // Use SetWindowLongPtr if available (64-bit safe)
                        lib.SetWindowLongPtr(hMsnWnd, GWL_WNDPROC, WNDPROC);
                        //System.err.println("Registered 64-bit callback");
                    } catch(UnsatisfiedLinkError e) {
                        // Use SetWindowLong if SetWindowLongPtr isn't available
                        lib.SetWindowLong(hMsnWnd, GWL_WNDPROC, WNDPROC);
                        //System.err.println("Registered 32-bit callback");
                    }
                    // Handle events until the window is destroyed
                    MSG msg = new MSG();
                    msg.clear();
                    while(lib.GetMessage(msg, hMsnWnd, 0, 0) > 0) {
                        lib.TranslateMessage(msg);                                 
                        lib.DispatchMessage(msg);
                    }
                }
            }
        }
    }

(Full code link)

matthiasblaesing commented 7 years ago

Can you give the full exception trace?

agaertner commented 7 years ago

Yes, I can

    02-03-2017 @ 22:53:19Z (Thread[Thread-44,5,main]) java.lang.NoSuchFieldError: DEFAULT
    at com.sun.jna.platform.win32.WinUser$WNDCLASSEX.<init>(WinUser.java:1187)
    at com.nekres.MSNeventListener$MsnMessagePump.run(MSNeventListener.java:94)
    at java.lang.Thread.run(Unknown Source)

The library loads correctly. The error is happening in the WNDCLASSEX. Rebuilding my project from scratch doesn't fix it. Must be because of the synchronized(msnWndHandle) object. Can't seem to fix it. I need the thread looping and joining.

matthiasblaesing commented 7 years ago

You are running with an old version of JNA - this is the code:

        public WNDCLASSEX() {
            super(W32APITypeMapper.DEFAULT);
        }

The W32APITypeMapper.DEFAULT was introduced in the JNA 4.3.0 cycle. So if you have an older JNA jar on your classpath it might pick the wrong class. Check you classpath!

agaertner commented 7 years ago

I checked the WNDCLASSEX code, but I downloaded the newest libaries jna and jna-platform 4.3.0 and the error still occured.

Again, the class is working as intended when testing in BlueJ, but in my project (after building with Eclipse and running the application) it errors at WNDCLASSEX.

now tried to set native library location in Eclipse (c:/windows/system32) for both jna-4.3.0.jar and jna-platform-4.3.0.jar, but still get the same stacktrace. :/

matthiasblaesing commented 7 years ago

Ok - your error is pretty clear:

 02-03-2017 @ 22:53:19Z (Thread[Thread-44,5,main]) java.lang.NoSuchFieldError: DEFAULT
    at com.sun.jna.platform.win32.WinUser$WNDCLASSEX.<init>(WinUser.java:1187)

it basicly says: There is no field with the name DEFAULT in class W32APITypeMapper (the class is deduced from source code of com.sun.jna.platform.win32.WinUser).

This is only the case before JNA 4.3.0 - I just checked the jars on github in the dist folder and the maven jar and both contain the class + field:

matthias@athena:~/x$ javap  com/sun/jna/win32/W32APITypeMapper.class 
Compiled from "W32APITypeMapper.java"
public class com.sun.jna.win32.W32APITypeMapper extends com.sun.jna.DefaultTypeMapper {
  public static final com.sun.jna.TypeMapper UNICODE;
  public static final com.sun.jna.TypeMapper ASCII;
  public static final com.sun.jna.TypeMapper DEFAULT;
  protected com.sun.jna.win32.W32APITypeMapper(boolean);
  static {};
}
matthias@athena:~/x$ 

I'll risk a guess: You don't run the code stand alone, but use it from other code. That project has its own dependencies and if there is another JNA jar referenced, this explains it. Can you show the complete source code and runtime?

agaertner commented 7 years ago

I wrote the MSNeventListener myself. It is basically a translation to java of https://github.com/Piotrekol/MSN-event-listener (listener.cs)

The project I am building is https://github.com/Nekress/PhantomBot/tree/Nekress_osuToMsnAdapter (forked)

the MSNeventListener gets created in the PhantomBot.java (source/com/me/mast3rplan/)

I added the project to Eclipse, added all the previous libraries plus the JNA in the properties window of the project explorer (right click -> properties -> Add external JARs) I then expanded the jna-*.jar's and added the Native library path JNA depends on (c:/windows/system32)

I was told Eclipse automatically sets paths so System.setProperties() is not needed.

matthiasblaesing commented 7 years ago

There is another JNA version on the classpath. The dependecies of PhantomBot should not depend on this:

JDA-withDependencies-2.3.0_379.jar

This jar bundles a load of dependencies:

I strongly advise against using such "bundle everything you need" jars as dependencies.

matthiasblaesing commented 7 years ago

@Nekress I forgot another option: As PhantomBot embedds jna 4.2.2, you could use jna-platform 4.2.2. That way you can go on and it should work.