eclipse-openj9 / openj9

Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.
Other
3.27k stars 721 forks source link

OpenJ9 cannot load/find/link .jnilib files on macOS; when renamed to .dylib, it works #5707

Closed rubin55 closed 5 years ago

rubin55 commented 5 years ago

When running some applications with OpenJ9 that depend on some Java Native Interface stuff on macOS, OpenJ9 seems to not be able to load those dependencies when they're called <something>.jnilib. It will load them when one renames or links to the files with a <something>.dylib name.

Here's some error output from Tanuki wrapper as used within Anypoint Studio (an Eclipse based IDE):

Java Service Wrapper Standard Edition 64-bit 3.5.37
  Copyright (C) 1999-2018 Tanuki Software, Ltd. All Rights Reserved.
    http://wrapper.tanukisoftware.com
  Licensed to MuleSoft Inc. for Mule Runtime Enterprise Edition

Launching a JVM...
Starting the Mule Container...
WrapperManager: Initializing...
WrapperManager: 
WrapperManager: ERROR - Unable to load the Wrapper's native library because none of the
WrapperManager:         following files:
WrapperManager:           libwrapper-macosx-universal-64.dylib
WrapperManager:           libwrapper.dylib
WrapperManager:         could be located on the following java.library.path:
WrapperManager:           /Applications/Anypoint Studio 7.app/Contents/Eclipse/configuration/org.eclipse.osgi/506/data/.runtimes/tooling-em0uavkj/lib/boot
WrapperManager:         Please see the documentation for the wrapper.java.library.path
WrapperManager:         configuration property.
WrapperManager: 
Writing to the backend pipe failed (35): Resource temporarily unavailable
Pipe send failed.  Incomplete.  Sent 8051 of 15226 bytes.
Writing to the backend pipe failed (35): Resource temporarily unavailable
Pipe send failed.  Incomplete.  Sent 0 of 2 bytes.

When I enter the above mentioned directory ([..]/lib/boot) I don't see a file named libwrapper-macosx-universal-64.dylib, but I do see a file named libwrapper-macosx-universal-64.jnilib. Note the extension. Renaming or linking to the file makes the wrapper work. This problem does not occur on Hotspot.

DanHeidinga commented 5 years ago

After a bit of digging, it sounds like the order is:

Likely something we need to change in ClassLoader loadLibraryWithPath or maybe loadLibraryWithClassLoader

DanHeidinga commented 5 years ago

@fengxue-IS Can you take a look at this?

fengxue-IS commented 5 years ago

Looking into this

fengxue-IS commented 5 years ago

We are using port library api j9sl_open_shared_library for loading libraries, the file extension is defined in OMR https://github.com/eclipse/omr/blob/cfeaf3a68032d9cf352d53c07abce500b4fa98cf/port/unix/omrsl.c#L76-L80 I'll update the api to check for .jnilib suffix if it failed to locate library using .dylib

@DanHeidinga JVM also uses this suffix during the preloadLibrary method, https://github.com/eclipse/openj9/blob/3a46f0e858546387c6740de2f89cba607bf590d1/runtime/j9vm/jvm.c#L2395-L2397

Is there a need to update this as well? (My understanding is that preloadLibrary is only for internal libraries which doesn't use the .jnilib suffix)

DanHeidinga commented 5 years ago

Is there a need to update this as well?

No, we don't need to update the internal preloadLibrary calls

fengxue-IS commented 5 years ago

PR WIP: https://github.com/eclipse/omr/pull/3850

DanHeidinga commented 5 years ago

@fengxue-IS Can we control this behaviour from OpenJ9 rather than OMR? My assumption is we'd attempt to do the load as a .dylib and only if it fails, fall back to .jnilib.

Maybe by hacking the code in https://github.com/eclipse/openj9/blob/3ce824471411143746d7f749c5391a4c4e5a5c3c/runtime/vm/vmbootlib.c#L250-L252

fengxue-IS commented 5 years ago

@DanHeidinga the platform dependent file name (ie. lib<name>.dylib) is filled in the port API automatically.

If we want to have the code in OpenJ9, we would have to copy some of that functionality from OMR to expend the lib name before passing into omrsl_open_shared_library()

If this is the preferred solution, I'll close the PR in OMR and move the changes into OpenJ9

DanHeidinga commented 5 years ago

It seems odd to add to OMR a very java-specific sharedlibrary suffix like .jnilib.

It's reasonable for OpenJ9 to either pass in the library name or maybe to add a new API to OMR to register alternative sharedlibrary suffixes.

fengxue-IS commented 5 years ago

Will talk to OMR reviewer whether adding new API for alternative suffixes is feasible.

fengxue-IS commented 5 years ago

On second though, this would be more straight forward to implement in OpenJ9 by removing the decorate flag and pre-expending the full name of the library.