Native libraries: support loading via System.loadLibrary()

(for pre-extracted native libs in NetBeans)
This commit is contained in:
Karl Tauber
2022-10-06 10:49:55 +02:00
parent 1a456d5d68
commit 8e42b19934
4 changed files with 66 additions and 14 deletions

View File

@@ -3,6 +3,11 @@ FlatLaf Change Log
## 3.0-SNAPSHOT
#### New features and improvements
- If value of system property `flatlaf.nativeLibraryPath` is `system`, then
`System.loadLibrary(String)` is used to load the native library.
#### Fixed bugs
- ComboBox and Spinner: Fixed missing arrow buttons if preferred height is zero.

View File

@@ -155,9 +155,19 @@ public interface FlatSystemProperties
String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange";
/**
* Specifies a directory in which the native FlatLaf library have been extracted.
* Specifies a directory in which the native FlatLaf libraries have been extracted.
* The path can be absolute or relative to current application working directory.
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
* <p>
* If the value is {@code "system"}, then {@link System#loadLibrary(String)} is
* used to load the native library.
* Searches for the native library in classloader of caller
* (using {@link ClassLoader#findLibrary(String)}) and in paths specified
* in system properties {@code sun.boot.library.path} and {@code java.library.path}.
* (supported since FlatLaf 3)
* <p>
* If the native library can not loaded from the given path (or via {@link System#loadLibrary(String)}),
* then the embedded native library is extracted to the temporary directory and loaded from there.
*
* @since 2
*/

View File

@@ -84,11 +84,19 @@ class FlatNativeLibrary
private static NativeLibrary createNativeLibrary( String libraryName ) {
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
if( libraryPath != null ) {
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
if( libraryFile.exists() )
return new NativeLibrary( libraryFile, true );
else
if( "system".equals( libraryPath ) ) {
NativeLibrary library = new NativeLibrary( libraryName, true );
if( library.isLoaded() )
return library;
LoggingFacade.INSTANCE.logSevere( "Did not find library " + libraryName + " in java.library.path, using extracted library instead", null );
} else {
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
if( libraryFile.exists() )
return new NativeLibrary( libraryFile, true );
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
}
}
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
@@ -101,9 +109,9 @@ class FlatNativeLibrary
// log error only if native library jawt.dll not already loaded
String message = ex.getMessage();
if( message == null || !message.contains( "already loaded in another classloader" ) )
LoggingFacade.INSTANCE.logSevere( null, ex );
LoggingFacade.INSTANCE.logSevere( message, ex );
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
}
}
}

View File

@@ -73,6 +73,22 @@ public class NativeLibrary
: false;
}
/**
* Load native library using {@link System#loadLibrary(String)}.
* Searches for the library in classloader of caller
* (using {@link ClassLoader#findLibrary(String)}) and in paths specified
* in system properties {@code sun.boot.library.path} and {@code java.library.path}.
*
* @param libraryName name of the native library (without "lib" prefix and without extension)
* @param supported whether the native library is supported on the current platform
* @since 3
*/
public NativeLibrary( String libraryName, boolean supported ) {
this.loaded = supported
? loadLibraryFromSystem( libraryName )
: false;
}
/**
* Returns whether the native library is loaded.
* <p>
@@ -92,7 +108,7 @@ public class NativeLibrary
? classLoader.getResource( libraryName )
: NativeLibrary.class.getResource( "/" + libraryName );
if( libraryUrl == null ) {
log( "Library '" + libraryName + "' not found", null );
LoggingFacade.INSTANCE.logSevere( "Library '" + libraryName + "' not found", null );
return false;
}
@@ -125,7 +141,7 @@ public class NativeLibrary
return true;
} catch( Throwable ex ) {
log( null, ex );
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
if( tempFile != null )
deleteOrMarkForDeletion( tempFile );
@@ -138,7 +154,24 @@ public class NativeLibrary
System.load( libraryFile.getAbsolutePath() );
return true;
} catch( Throwable ex ) {
log( ex.getMessage(), ex );
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
return false;
}
}
private boolean loadLibraryFromSystem( String libraryName ) {
try {
System.loadLibrary( libraryName );
return true;
} catch( Throwable ex ) {
String message = ex.getMessage();
// do not log error if library was not found
// thrown in ClassLoader.loadLibrary(Class<?> fromClass, String name, boolean isAbsolute)
if( ex instanceof UnsatisfiedLinkError && message != null && message.contains( "java.library.path" ) )
return false;
LoggingFacade.INSTANCE.logSevere( message, ex );
return false;
}
}
@@ -158,10 +191,6 @@ public class NativeLibrary
: System.mapLibraryName( libraryName );
}
private static void log( String msg, Throwable thrown ) {
LoggingFacade.INSTANCE.logSevere( msg, thrown );
}
private static Path createTempFile( String libraryName ) throws IOException {
int sep = libraryName.lastIndexOf( '/' );
String name = (sep >= 0) ? libraryName.substring( sep + 1 ) : libraryName;