summaryrefslogtreecommitdiffstats
path: root/java_jni
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2021-01-25 01:28:36 +0100
committerSven Gothel <[email protected]>2021-01-25 01:28:36 +0100
commitb371af6d83e0fb94cba02ec6c2837bf58c2eea39 (patch)
tree48999c7e269409ebe389e5d5e72ca141d8b9eea7 /java_jni
parent1ba932716f2d382af56bf8ea69a57666e2c835d6 (diff)
Java import and modularization: jaulib_base, jaulib_jni, jaulib_net, jaulib_pkg (WIP)
Diffstat (limited to 'java_jni')
-rw-r--r--java_jni/CMakeLists.txt21
-rw-r--r--java_jni/jau/sys/MachineDataInfoRuntime.java155
-rw-r--r--java_jni/jau/sys/dl/BionicDynamicLinker32bitImpl.java61
-rw-r--r--java_jni/jau/sys/dl/BionicDynamicLinker64BitImpl.java61
-rw-r--r--java_jni/jau/sys/dl/DynamicLinkerImpl.java215
-rw-r--r--java_jni/jau/sys/dl/MacOSXDynamicLinkerImpl.java57
-rw-r--r--java_jni/jau/sys/dl/PosixDynamicLinkerImpl.java52
-rw-r--r--java_jni/jau/sys/dl/UnixDynamicLinkerImpl.java64
-rw-r--r--java_jni/jau/sys/dl/WindowsDynamicLinkerImpl.java92
-rw-r--r--java_jni/jni/CMakeLists.txt42
-rw-r--r--java_jni/jni/helper_jni.cxx354
-rw-r--r--java_jni/jni/jau/Clock.cxx65
-rw-r--r--java_jni/jni/jau/JVM_JNI8.cxx46
-rw-r--r--java_jni/jni/jau/MachineDataInfoRuntime.cxx211
-rw-r--r--java_jni/jni/jau/UnixDynamicLinkerImpl_JNI.cxx138
-rw-r--r--java_jni/jni/jau/WindowsDynamicLinkerImpl_JNI.cxx107
-rw-r--r--java_jni/jni/jni_mem.cxx169
-rw-r--r--java_jni/manifest.txt.in30
-rw-r--r--java_jni/org/jau/sys/Clock.java53
-rw-r--r--java_jni/org/jau/sys/dl/DynamicLibraryBundle.java422
-rw-r--r--java_jni/org/jau/sys/dl/DynamicLibraryBundleInfo.java128
-rw-r--r--java_jni/org/jau/sys/dl/DynamicLinker.java113
-rw-r--r--java_jni/org/jau/sys/dl/DynamicLookupHelper.java57
-rw-r--r--java_jni/org/jau/sys/dl/NativeLibrary.java298
24 files changed, 3011 insertions, 0 deletions
diff --git a/java_jni/CMakeLists.txt b/java_jni/CMakeLists.txt
new file mode 100644
index 0000000..e758520
--- /dev/null
+++ b/java_jni/CMakeLists.txt
@@ -0,0 +1,21 @@
+# java/CMakeLists.txt
+
+set(CMAKE_JNI_TARGET TRUE)
+file(GLOB_RECURSE JAVA_SOURCES "*.java")
+add_jar(jaulib_jni_jar
+ ${JAVA_SOURCES}
+ INCLUDE_JARS jaulib_base_jar
+ MANIFEST ${CMAKE_CURRENT_BINARY_DIR}/manifest.txt
+ OUTPUT_NAME jaulib_jni
+ GENERATE_NATIVE_HEADERS jaulib_jni_javah
+ DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/jaulib_jni_jar.dir/jni"
+)
+add_dependencies(jaulib_jni_jar jaulib_base_jar)
+#add_dependencies(jaulib_net_jar jaulib_base_jar jaulib_jni_jar)
+#add_dependencies(jaulib_pkg_jar jaulib_base_jar jaulib_jni_jar jaulib_net_jar)
+
+set(JNI_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/jaulib_jni_jar.dir/jni")
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/jaulib_jni.jar DESTINATION ${CMAKE_INSTALL_LIBDIR}/../lib/java)
+
+add_subdirectory (jni)
+
diff --git a/java_jni/jau/sys/MachineDataInfoRuntime.java b/java_jni/jau/sys/MachineDataInfoRuntime.java
new file mode 100644
index 0000000..d024bf6
--- /dev/null
+++ b/java_jni/jau/sys/MachineDataInfoRuntime.java
@@ -0,0 +1,155 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2010 Gothel Software e.K.
+ * Copyright (c) 2010 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jau.sys;
+
+import org.jau.sys.MachineDataInfo;
+import org.jau.sys.MachineDataInfo.StaticConfig;
+import org.jau.sys.PlatformProps;
+import org.jau.sys.PlatformTypes;
+
+/**
+ * Runtime operations of {@link MachineDataInfo}.
+ */
+public class MachineDataInfoRuntime {
+
+ static volatile boolean initialized = false;
+ static volatile MachineDataInfo runtimeMD = null;
+ static volatile MachineDataInfo.StaticConfig staticMD = null;
+
+ public static void initialize() {
+ if( !initialized ) {
+ synchronized(MachineDataInfo.class) { // volatile dbl-checked-locking OK
+ if( !initialized ) {
+ MachineDataInfo.StaticConfig.validateUniqueMachineDataInfo();
+
+ final MachineDataInfo runtimeMD = getRuntimeImpl();
+ final MachineDataInfo.StaticConfig staticMD = MachineDataInfo.StaticConfig.findCompatible(runtimeMD);
+ if( null == staticMD ) {
+ throw new RuntimeException("No compatible MachineDataInfo.StaticConfig for runtime:"+PlatformProps.NEWLINE+runtimeMD);
+ }
+ if( !staticMD.md.compatible(runtimeMD) ) {
+ throw new RuntimeException("Incompatible MachineDataInfo:"+PlatformProps.NEWLINE+
+ " Static "+staticMD+PlatformProps.NEWLINE+
+ " Runtime "+runtimeMD);
+ }
+ MachineDataInfoRuntime.runtimeMD = runtimeMD;
+ MachineDataInfoRuntime.staticMD = staticMD;
+ initialized=true;
+ if( PlatformProps.DEBUG ) {
+ System.err.println("MachineDataInfoRuntime.initialize():"+PlatformProps.NEWLINE+
+ " Static "+staticMD+PlatformProps.NEWLINE+
+ " Runtime "+runtimeMD);
+ }
+ return;
+ }
+ }
+ }
+ throw new InternalError("Already initialized");
+ }
+ /**
+ * The static {@link MachineDataInfo} is utilized for high performance
+ * precompiled size, offset, etc table lookup within generated structures
+ * using the {@link MachineDataInfo.StaticConfig} index.
+ */
+ public static MachineDataInfo.StaticConfig getStatic() {
+ if(!initialized) {
+ synchronized(MachineDataInfo.class) { // volatile dbl-checked-locking OK
+ if(!initialized) {
+ throw new InternalError("Not set");
+ }
+ }
+ }
+ return staticMD;
+ }
+ public static MachineDataInfo getRuntime() {
+ if(!initialized) {
+ synchronized(MachineDataInfo.class) { // volatile dbl-checked-locking OK
+ if(!initialized) {
+ throw new InternalError("Not set");
+ }
+ }
+ }
+ return runtimeMD;
+ }
+
+ private static MachineDataInfo getRuntimeImpl() {
+ try {
+ PlatformProps.initSingleton();
+ } catch (final Throwable err) {
+ return null;
+ }
+
+ final int pointerSizeInBytes = getPointerSizeInBytesImpl();
+ switch(pointerSizeInBytes) {
+ case 4:
+ case 8:
+ break;
+ default:
+ throw new RuntimeException("Unsupported pointer size "+pointerSizeInBytes+"bytes, please implement.");
+ }
+
+ final long pageSizeL = getPageSizeInBytesImpl();
+ if(Integer.MAX_VALUE < pageSizeL) {
+ throw new InternalError("PageSize exceeds integer value: " + pageSizeL);
+ }
+
+ // size: int, long, float, double, pointer, pageSize
+ // alignment: int8, int16, int32, int64, int, long, float, double, pointer
+ return new MachineDataInfo(
+ true /* runtime validated */,
+
+ getSizeOfIntImpl(), getSizeOfLongImpl(),
+ getSizeOfFloatImpl(), getSizeOfDoubleImpl(), getSizeOfLongDoubleImpl(),
+ pointerSizeInBytes, (int)pageSizeL,
+
+ getAlignmentInt8Impl(), getAlignmentInt16Impl(), getAlignmentInt32Impl(), getAlignmentInt64Impl(),
+ getAlignmentIntImpl(), getAlignmentLongImpl(),
+ getAlignmentFloatImpl(), getAlignmentDoubleImpl(), getAlignmentLongDoubleImpl(),
+ getAlignmentPointerImpl());
+ }
+
+ private static native int getPointerSizeInBytesImpl();
+ private static native long getPageSizeInBytesImpl();
+
+ private static native int getAlignmentInt8Impl();
+ private static native int getAlignmentInt16Impl();
+ private static native int getAlignmentInt32Impl();
+ private static native int getAlignmentInt64Impl();
+ private static native int getAlignmentIntImpl();
+ private static native int getAlignmentLongImpl();
+ private static native int getAlignmentPointerImpl();
+ private static native int getAlignmentFloatImpl();
+ private static native int getAlignmentDoubleImpl();
+ private static native int getAlignmentLongDoubleImpl();
+ private static native int getSizeOfIntImpl();
+ private static native int getSizeOfLongImpl();
+ private static native int getSizeOfPointerImpl();
+ private static native int getSizeOfFloatImpl();
+ private static native int getSizeOfDoubleImpl();
+ private static native int getSizeOfLongDoubleImpl();
+}
+
diff --git a/java_jni/jau/sys/dl/BionicDynamicLinker32bitImpl.java b/java_jni/jau/sys/dl/BionicDynamicLinker32bitImpl.java
new file mode 100644
index 0000000..9aa8c02
--- /dev/null
+++ b/java_jni/jau/sys/dl/BionicDynamicLinker32bitImpl.java
@@ -0,0 +1,61 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+/**
+ * Bionic 32bit specialization of {@link UnixDynamicLinkerImpl}
+ * utilizing Bionic's non POSIX flags and mode values.
+ * <p>
+ * Bionic is used on Android.
+ * </p>
+ */
+public final class BionicDynamicLinker32bitImpl extends UnixDynamicLinkerImpl {
+
+ // static final int RTLD_NOW = 0x00000;
+ private static final int RTLD_LAZY = 0x00001;
+
+ private static final int RTLD_LOCAL = 0x00000;
+ private static final int RTLD_GLOBAL = 0x00002;
+ // static final int RTLD_NOLOAD = 0x00004;
+
+ private static final long RTLD_DEFAULT = 0xffffffffL;
+ // static final long RTLD_NEXT = 0xfffffffeL;
+
+ @Override
+ protected final long openLibraryLocalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
+ }
+
+ @Override
+ protected final long openLibraryGlobalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
+ }
+
+ @Override
+ protected final long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException {
+ return dlsym(RTLD_DEFAULT, symbolName);
+ }
+}
diff --git a/java_jni/jau/sys/dl/BionicDynamicLinker64BitImpl.java b/java_jni/jau/sys/dl/BionicDynamicLinker64BitImpl.java
new file mode 100644
index 0000000..bfbc7f0
--- /dev/null
+++ b/java_jni/jau/sys/dl/BionicDynamicLinker64BitImpl.java
@@ -0,0 +1,61 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2015 Gothel Software e.K.
+ * Copyright (c) 2015 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+/**
+ * Bionic 64bit specialization of {@link UnixDynamicLinkerImpl}
+ * utilizing Bionic's non POSIX flags and mode values.
+ * <p>
+ * Bionic is used on Android.
+ * </p>
+ */
+public final class BionicDynamicLinker64BitImpl extends UnixDynamicLinkerImpl {
+ // static final int RTLD_NOW = 0x00002;
+ private static final int RTLD_LAZY = 0x00001;
+
+ private static final int RTLD_LOCAL = 0x00000;
+ private static final int RTLD_GLOBAL = 0x00100;
+ // static final int RTLD_NOLOAD = 0x00004;
+
+ private static final long RTLD_DEFAULT = 0x00000000L;
+ // static final long RTLD_NEXT = -1L;
+
+ @Override
+ protected final long openLibraryLocalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
+ }
+
+ @Override
+ protected final long openLibraryGlobalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
+ }
+
+ @Override
+ protected final long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException {
+ return dlsym(RTLD_DEFAULT, symbolName);
+ }
+
+}
diff --git a/java_jni/jau/sys/dl/DynamicLinkerImpl.java b/java_jni/jau/sys/dl/DynamicLinkerImpl.java
new file mode 100644
index 0000000..407666e
--- /dev/null
+++ b/java_jni/jau/sys/dl/DynamicLinkerImpl.java
@@ -0,0 +1,215 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+import java.util.HashMap;
+
+import org.jau.sec.SecurityUtil;
+import org.jau.sys.dl.DynamicLinker;
+
+/* pp */ abstract class DynamicLinkerImpl implements DynamicLinker {
+
+ //
+ // Package private scope of class w/ protected native code access
+ // and sealed jogamp.common.* package definition
+ // ensuring no abuse via subclassing.
+ //
+
+ private final Object secSync = new Object();
+ private boolean allLinkPermissionGranted = false;
+
+ /**
+ * @throws SecurityException if user is not granted global access
+ */
+ @Override
+public final void claimAllLinkPermission() throws SecurityException {
+ synchronized( secSync ) {
+ allLinkPermissionGranted = true;
+ }
+ }
+
+ /**
+ * @throws SecurityException if user is not granted global access
+ */
+ @Override
+public final void releaseAllLinkPermission() throws SecurityException {
+ synchronized( secSync ) {
+ allLinkPermissionGranted = false;
+ }
+ }
+
+ private final void checkLinkPermission(final String pathname) throws SecurityException {
+ synchronized( secSync ) {
+ if( !allLinkPermissionGranted ) {
+ SecurityUtil.checkLinkPermission(pathname);
+ }
+ }
+ }
+ private final void checkLinkPermission(final long libraryHandle) throws SecurityException {
+ synchronized( secSync ) {
+ if( !allLinkPermissionGranted ) {
+ final LibRef libRef = getLibRef( libraryHandle );
+ if( null == libRef ) {
+ throw new IllegalArgumentException("Library handle 0x"+Long.toHexString(libraryHandle)+" unknown.");
+ }
+ SecurityUtil.checkLinkPermission(libRef.getName());
+ }
+ }
+ }
+
+ private final void checkAllLinkPermission() throws SecurityException {
+ synchronized( secSync ) {
+ if( !allLinkPermissionGranted ) {
+ SecurityUtil.checkAllLinkPermission();
+ }
+ }
+ }
+
+ @Override
+ public final long openLibraryGlobal(final String pathname, final boolean debug) throws SecurityException {
+ checkLinkPermission(pathname);
+ final long handle = openLibraryGlobalImpl(pathname);
+ if( 0 != handle ) {
+ final LibRef libRef = incrLibRefCount(handle, pathname);
+ if( DEBUG || debug ) {
+ System.err.println("DynamicLinkerImpl.openLibraryGlobal \""+pathname+"\": 0x"+Long.toHexString(handle)+" -> "+libRef+")");
+ }
+ } else if ( DEBUG || debug ) {
+ System.err.println("DynamicLinkerImpl.openLibraryGlobal \""+pathname+"\" failed, error: "+getLastError());
+ }
+ return handle;
+ }
+ protected abstract long openLibraryGlobalImpl(final String pathname) throws SecurityException;
+
+ @Override
+ public final long openLibraryLocal(final String pathname, final boolean debug) throws SecurityException {
+ checkLinkPermission(pathname);
+ final long handle = openLibraryLocalImpl(pathname);
+ if( 0 != handle ) {
+ final LibRef libRef = incrLibRefCount(handle, pathname);
+ if( DEBUG || debug ) {
+ System.err.println("DynamicLinkerImpl.openLibraryLocal \""+pathname+"\": 0x"+Long.toHexString(handle)+" -> "+libRef+")");
+ }
+ } else if ( DEBUG || debug ) {
+ System.err.println("DynamicLinkerImpl.openLibraryLocal \""+pathname+"\" failed, error: "+getLastError());
+ }
+ return handle;
+ }
+ protected abstract long openLibraryLocalImpl(final String pathname) throws SecurityException;
+
+ @Override
+ public final long lookupSymbolGlobal(final String symbolName) throws SecurityException {
+ checkAllLinkPermission();
+ final long addr = lookupSymbolGlobalImpl(symbolName);
+ if(DEBUG_LOOKUP) {
+ System.err.println("DynamicLinkerImpl.lookupSymbolGlobal("+symbolName+") -> 0x"+Long.toHexString(addr));
+ }
+ return addr;
+ }
+ protected abstract long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException;
+
+ @Override
+ public final long lookupSymbol(final long libraryHandle, final String symbolName) throws SecurityException, IllegalArgumentException {
+ checkLinkPermission(libraryHandle);
+ final long addr = lookupSymbolLocalImpl(libraryHandle, symbolName);
+ if(DEBUG_LOOKUP) {
+ System.err.println("DynamicLinkerImpl.lookupSymbol(0x"+Long.toHexString(libraryHandle)+", "+symbolName+") -> 0x"+Long.toHexString(addr));
+ }
+ return addr;
+ }
+ protected abstract long lookupSymbolLocalImpl(final long libraryHandle, final String symbolName) throws SecurityException;
+
+ @Override
+ public final void closeLibrary(final long libraryHandle, final boolean debug) throws SecurityException, IllegalArgumentException {
+ final LibRef libRef = decrLibRefCount( libraryHandle );
+ if( null != libRef ) {
+ checkLinkPermission(libRef.getName());
+ } // else null libRef is OK for global lookup
+ if( DEBUG || debug ) {
+ System.err.println("DynamicLinkerImpl.closeLibrary(0x"+Long.toHexString(libraryHandle)+" -> "+libRef+")");
+ }
+ if( 0 != libraryHandle ) {
+ closeLibraryImpl(libraryHandle);
+ }
+ }
+ protected abstract void closeLibraryImpl(final long libraryHandle) throws SecurityException;
+
+ private static final HashMap<Long,Object> libHandle2Name = new HashMap<Long,Object>( 16 /* initialCapacity */ );
+
+ static final class LibRef {
+ LibRef(final String name) {
+ this.name = name;
+ this.refCount = 1;
+ }
+ final int incrRefCount() { return ++refCount; }
+ final int decrRefCount() { return --refCount; }
+ final int getRefCount() { return refCount; }
+
+ final String getName() { return name; }
+ @Override
+ public final String toString() { return "LibRef["+name+", refCount "+refCount+"]"; }
+
+ private final String name;
+ private int refCount;
+ }
+
+ private final LibRef getLibRef(final long handle) {
+ synchronized( libHandle2Name ) {
+ return (LibRef) libHandle2Name.get(handle);
+ }
+ }
+
+ private final LibRef incrLibRefCount(final long handle, final String libName) {
+ synchronized( libHandle2Name ) {
+ LibRef libRef = getLibRef(handle);
+ if( null == libRef ) {
+ libRef = new LibRef(libName);
+ libHandle2Name.put(handle, libRef);
+ } else {
+ libRef.incrRefCount();
+ }
+ if(DEBUG) {
+ System.err.println("DynamicLinkerImpl.incrLibRefCount 0x"+Long.toHexString(handle)+ " -> "+libRef+", libs loaded "+libHandle2Name.size());
+ }
+ return libRef;
+ }
+ }
+
+ private final LibRef decrLibRefCount(final long handle) {
+ synchronized( libHandle2Name ) {
+ final LibRef libRef = getLibRef(handle);
+ if( null != libRef ) {
+ if( 0 == libRef.decrRefCount() ) {
+ libHandle2Name.remove(handle);
+ }
+ }
+ if(DEBUG) {
+ System.err.println("DynamicLinkerImpl.decrLibRefCount 0x"+Long.toHexString(handle)+ " -> "+libRef+", libs loaded "+libHandle2Name.size());
+ }
+ return libRef;
+ }
+ }
+}
diff --git a/java_jni/jau/sys/dl/MacOSXDynamicLinkerImpl.java b/java_jni/jau/sys/dl/MacOSXDynamicLinkerImpl.java
new file mode 100644
index 0000000..68c70da
--- /dev/null
+++ b/java_jni/jau/sys/dl/MacOSXDynamicLinkerImpl.java
@@ -0,0 +1,57 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+/**
+ * Mac OS X specialization of {@link UnixDynamicLinkerImpl}
+ * utilizing OS X 's non POSIX flags and mode values.
+ */
+public final class MacOSXDynamicLinkerImpl extends UnixDynamicLinkerImpl {
+
+ private static final long RTLD_DEFAULT = -2L;
+ // static final long RTLD_NEXT = -1L;
+
+ private static final int RTLD_LAZY = 0x00001;
+ // static final int RTLD_NOW = 0x00002;
+ private static final int RTLD_LOCAL = 0x00004;
+ private static final int RTLD_GLOBAL = 0x00008;
+
+ @Override
+ protected final long openLibraryLocalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
+ }
+
+ @Override
+ protected final long openLibraryGlobalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
+ }
+
+ @Override
+ protected final long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException {
+ return dlsym(RTLD_DEFAULT, symbolName);
+ }
+
+}
diff --git a/java_jni/jau/sys/dl/PosixDynamicLinkerImpl.java b/java_jni/jau/sys/dl/PosixDynamicLinkerImpl.java
new file mode 100644
index 0000000..438fa9a
--- /dev/null
+++ b/java_jni/jau/sys/dl/PosixDynamicLinkerImpl.java
@@ -0,0 +1,52 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+public final class PosixDynamicLinkerImpl extends UnixDynamicLinkerImpl {
+
+ private static final long RTLD_DEFAULT = 0;
+ // private static final long RTLD_NEXT = -1L;
+
+ private static final int RTLD_LAZY = 0x00001;
+ // private static final int RTLD_NOW = 0x00002;
+ private static final int RTLD_LOCAL = 0x00000;
+ private static final int RTLD_GLOBAL = 0x00100;
+
+ @Override
+ protected final long openLibraryLocalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
+ }
+
+ @Override
+ protected final long openLibraryGlobalImpl(final String pathname) throws SecurityException {
+ return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
+ }
+
+ @Override
+ protected final long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException {
+ return dlsym(RTLD_DEFAULT, symbolName);
+ }
+}
diff --git a/java_jni/jau/sys/dl/UnixDynamicLinkerImpl.java b/java_jni/jau/sys/dl/UnixDynamicLinkerImpl.java
new file mode 100644
index 0000000..fb25782
--- /dev/null
+++ b/java_jni/jau/sys/dl/UnixDynamicLinkerImpl.java
@@ -0,0 +1,64 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+/* pp */ abstract class UnixDynamicLinkerImpl extends DynamicLinkerImpl {
+
+ //
+ // Package private scope of class w/ protected native code access
+ // and sealed jogamp.common.* package definition
+ // ensuring no abuse via subclassing.
+ //
+
+ /** Interface to C language function: <br> <code> int dlclose(void * ); </code> */
+ protected static native int dlclose(long arg0);
+
+ /** Interface to C language function: <br> <code> char * dlerror(void); </code> */
+ protected static native java.lang.String dlerror();
+
+ /** Interface to C language function: <br> <code> void * dlopen(const char * , int); </code> */
+ protected static native long dlopen(java.lang.String arg0, int arg1);
+
+ /** Interface to C language function: <br> <code> void * dlsym(void * , const char * ); </code> */
+ protected static native long dlsym(long arg0, java.lang.String arg1);
+
+ @Override
+ protected final long lookupSymbolLocalImpl(final long libraryHandle, final String symbolName) throws SecurityException {
+ return 0 != libraryHandle ? dlsym(libraryHandle, symbolName) : 0;
+ }
+
+ @Override
+ protected final void closeLibraryImpl(final long libraryHandle) throws SecurityException {
+ if( 0 != libraryHandle ) {
+ dlclose(libraryHandle);
+ }
+ }
+
+ @Override
+ public final String getLastError() {
+ return dlerror();
+ }
+}
diff --git a/java_jni/jau/sys/dl/WindowsDynamicLinkerImpl.java b/java_jni/jau/sys/dl/WindowsDynamicLinkerImpl.java
new file mode 100644
index 0000000..9a4c8a5
--- /dev/null
+++ b/java_jni/jau/sys/dl/WindowsDynamicLinkerImpl.java
@@ -0,0 +1,92 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package jau.sys.dl;
+
+public final class WindowsDynamicLinkerImpl extends DynamicLinkerImpl {
+
+ /** Interface to C language function: <br> <code> BOOL FreeLibrary(HANDLE hLibModule); </code> */
+ private static native int FreeLibrary(long hLibModule);
+
+ /** Interface to C language function: <br> <code> DWORD GetLastError(void); </code> */
+ private static native int GetLastError();
+
+ /** Interface to C language function: <br> <code> PROC GetProcAddressA(HANDLE hModule, LPCSTR lpProcName); </code> */
+ private static native long GetProcAddressA(long hModule, java.lang.String lpProcName);
+
+ /** Interface to C language function: <br> <code> HANDLE LoadLibraryW(LPCWSTR lpLibFileName); </code> */
+ private static native long LoadLibraryW(java.lang.String lpLibFileName);
+
+ @Override
+ protected final long openLibraryLocalImpl(final String libraryName) throws SecurityException {
+ // How does that work under Windows ?
+ // Don't know .. so it's an alias to global, for the time being
+ return LoadLibraryW(libraryName);
+ }
+
+ @Override
+ protected final long openLibraryGlobalImpl(final String libraryName) throws SecurityException {
+ return LoadLibraryW(libraryName);
+ }
+
+ @Override
+ protected final long lookupSymbolGlobalImpl(final String symbolName) throws SecurityException {
+ if(DEBUG_LOOKUP) {
+ System.err.println("lookupSymbolGlobal: Not supported on Windows");
+ }
+ // allow DynamicLibraryBundle to continue w/ local libs
+ return 0;
+ }
+
+ private static final int symbolArgAlignment=4; // 4 byte alignment of each argument
+ private static final int symbolMaxArguments=12; // experience ..
+
+ @Override
+ protected final long lookupSymbolLocalImpl(final long libraryHandle, final String symbolName) throws IllegalArgumentException {
+ String _symbolName = symbolName;
+ long addr = GetProcAddressA(libraryHandle, _symbolName);
+ if( 0 == addr ) {
+ // __stdcall hack: try some @nn decorations,
+ // the leading '_' must not be added (same with cdecl)
+ for(int arg=0; 0==addr && arg<=symbolMaxArguments; arg++) {
+ _symbolName = symbolName+"@"+(arg*symbolArgAlignment);
+ addr = GetProcAddressA(libraryHandle, _symbolName);
+ }
+ }
+ return addr;
+ }
+
+ @Override
+ protected final void closeLibraryImpl(final long libraryHandle) throws IllegalArgumentException {
+ FreeLibrary(libraryHandle);
+ }
+
+ @Override
+ public final String getLastError() {
+ final int err = GetLastError();
+ return "Last error: 0x"+Integer.toHexString(err)+" ("+err+")";
+ }
+
+}
diff --git a/java_jni/jni/CMakeLists.txt b/java_jni/jni/CMakeLists.txt
new file mode 100644
index 0000000..5a0065c
--- /dev/null
+++ b/java_jni/jni/CMakeLists.txt
@@ -0,0 +1,42 @@
+find_package(JNI REQUIRED)
+
+set (jaulib_base_LIB_INCLUDE_DIRS
+ ${PROJECT_SOURCE_DIR}/include
+)
+
+include_directories(
+ ${JNI_INCLUDE_DIRS}
+ ${jaulib_base_LIB_INCLUDE_DIRS}
+ ${JNI_HEADER_PATH}
+)
+
+set (jaulib_jni_JNI_SRCS
+ ${PROJECT_SOURCE_DIR}/java_jni/jni/jni_mem.cxx
+ ${PROJECT_SOURCE_DIR}/java_jni/jni/helper_jni.cxx
+ ${PROJECT_SOURCE_DIR}/java_jni/jni/jau/JVM_JNI8.cxx
+ ${PROJECT_SOURCE_DIR}/java_jni/jni/jau/MachineDataInfoRuntime.cxx
+ ${PROJECT_SOURCE_DIR}/java_jni/jni/jau/Clock.cxx
+)
+
+if(WIN32)
+ set (jaulib_jni_JNI_SRCS ${jaulib_jni_JNI_SRCS} ${PROJECT_SOURCE_DIR}/java_jni/jni/jau/WindowsDynamicLinkerImpl_JNI.cxx)
+else()
+ set (jaulib_jni_JNI_SRCS ${jaulib_jni_JNI_SRCS} ${PROJECT_SOURCE_DIR}/java_jni/jni/jau/UnixDynamicLinkerImpl_JNI.cxx)
+endif()
+
+set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
+
+add_library (jaulib_jni_jni SHARED ${jaulib_jni_JNI_SRCS})
+target_link_libraries(jaulib_jni_jni ${JNI_LIBRARIES} jaulib)
+
+set_target_properties(
+ jaulib_jni_jni
+ PROPERTIES
+ SOVERSION ${jaulib_VERSION_MAJOR}
+ VERSION ${jaulib_VERSION_STRING}
+)
+
+install(TARGETS jaulib_jni_jni LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+add_dependencies(jaulib_jni_jni jaulib jaulib_base_jar jaulib_jni_jar)
+
diff --git a/java_jni/jni/helper_jni.cxx b/java_jni/jni/helper_jni.cxx
new file mode 100644
index 0000000..e083f8b
--- /dev/null
+++ b/java_jni/jni/helper_jni.cxx
@@ -0,0 +1,354 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Author: Andrei Vasiliu <[email protected]>
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <jni.h>
+#include <memory>
+#include <stdexcept>
+#include <vector>
+
+#include <jau/jni/helper_jni.hpp>
+
+using namespace jau;
+
+//
+// C++ <-> java exceptions
+//
+
+bool jau::java_exception_check(JNIEnv *env, const char* file, int line)
+{
+ jthrowable e = env->ExceptionOccurred();
+ if( nullptr != e ) {
+#if 1
+ // ExceptionDescribe prints an exception and a backtrace of the stack to a system error-reporting channel, such as stderr.
+ // The pending exception is cleared as a side-effect of calling this function. This is a convenience routine provided for debugging.
+ env->ExceptionDescribe();
+#endif
+ env->ExceptionClear(); // just be sure, to have same side-effects
+
+ jclass eClazz = search_class(env, e);
+ jmethodID toString = search_method(env, eClazz, "toString", "()Ljava/lang/String;", false);
+ jstring jmsg = (jstring) env->CallObjectMethod(e, toString);
+ std::string msg = from_jstring_to_string(env, jmsg);
+ fprintf(stderr, "Java exception occurred @ %s:%d and forward to Java: %s\n", file, line, msg.c_str()); fflush(stderr);
+
+ env->Throw(e); // re-throw the java exception - java side!
+ return true;
+ }
+ return false;
+}
+
+void jau::java_exception_check_and_throw(JNIEnv *env, const char* file, int line)
+{
+ jthrowable e = env->ExceptionOccurred();
+ if( nullptr != e ) {
+ // ExceptionDescribe prints an exception and a backtrace of the stack to a system error-reporting channel, such as stderr.
+ // The pending exception is cleared as a side-effect of calling this function. This is a convenience routine provided for debugging.
+ env->ExceptionDescribe();
+ env->ExceptionClear(); // just be sure, to have same side-effects
+
+ jclass eClazz = search_class(env, e);
+ jmethodID toString = search_method(env, eClazz, "toString", "()Ljava/lang/String;", false);
+ jstring jmsg = (jstring) env->CallObjectMethod(e, toString);
+ std::string msg = from_jstring_to_string(env, jmsg);
+ fprintf(stderr, "Java exception occurred @ %s:%d and forward to Native: %s\n", file, line, msg.c_str()); fflush(stderr);
+
+ throw jau::RuntimeException("Java exception occurred @ %s : %d: "+msg, file, line);
+ }
+}
+
+void jau::print_native_caught_exception_fwd2java(const std::exception &e, const char* file, int line) {
+ fprintf(stderr, "Native exception caught @ %s:%d and forward to Java: %s\n", file, line, e.what()); fflush(stderr);
+}
+void jau::print_native_caught_exception_fwd2java(const std::string &msg, const char* file, int line) {
+ fprintf(stderr, "Native exception caught @ %s:%d and forward to Java: %s\n", file, line, msg.c_str()); fflush(stderr);
+}
+void jau::print_native_caught_exception_fwd2java(const char * cmsg, const char* file, int line) {
+ fprintf(stderr, "Native exception caught @ %s:%d and forward to Java: %s\n", file, line, cmsg); fflush(stderr);
+}
+
+void jau::raise_java_exception(JNIEnv *env, const std::exception &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/Error"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const std::runtime_error &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::RuntimeException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::InternalError &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/InternalError"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::NullPointerException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/NullPointerException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::IllegalArgumentException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const std::invalid_argument &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::IllegalStateException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/IllegalStateException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::UnsupportedOperationException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/UnsupportedOperationException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::IndexOutOfBoundsException &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/IndexOutOfBoundsException"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const std::bad_alloc &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), e.what());
+}
+void jau::raise_java_exception(JNIEnv *env, const jau::OutOfMemoryError &e, const char* file, int line) {
+ print_native_caught_exception_fwd2java(e, file, line);
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), e.what());
+}
+
+static std::string _unknown_exception_type_msg("Unknown exception type");
+
+void jau::rethrow_and_raise_java_exception_jauimpl(JNIEnv *env, const char* file, int line) {
+ // std::exception_ptr e = std::current_exception();
+ try {
+ // std::rethrow_exception(e);
+ throw; // re-throw current exception
+ } catch (const std::bad_alloc &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::OutOfMemoryError &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::InternalError &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::NullPointerException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::IllegalArgumentException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::IllegalStateException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::UnsupportedOperationException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::IndexOutOfBoundsException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const jau::RuntimeException &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const std::runtime_error &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const std::invalid_argument &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const std::exception &e) {
+ jau::raise_java_exception(env, e, file, line);
+ } catch (const std::string &msg) {
+ jau::print_native_caught_exception_fwd2java(msg, file, line);
+ env->ThrowNew(env->FindClass("java/lang/Error"), msg.c_str());
+ } catch (const char *msg) {
+ jau::print_native_caught_exception_fwd2java(msg, file, line);
+ env->ThrowNew(env->FindClass("java/lang/Error"), msg);
+ } catch (...) {
+ jau::print_native_caught_exception_fwd2java(_unknown_exception_type_msg, file, line);
+ env->ThrowNew(env->FindClass("java/lang/Error"), _unknown_exception_type_msg.c_str());
+ }
+}
+
+//
+// Basic
+//
+
+jfieldID jau::getField(JNIEnv *env, jobject obj, const char* field_name, const char* field_signature) {
+ jclass clazz = env->GetObjectClass(obj);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ // J == long
+ jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ return res;
+}
+
+jclass jau::search_class(JNIEnv *env, const char *clazz_name)
+{
+ jclass clazz = env->FindClass(clazz_name);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ if (!clazz)
+ {
+ throw jau::InternalError(std::string("no class found: ")+clazz_name, E_FILE_LINE);
+ }
+ return clazz;
+}
+
+jclass jau::search_class(JNIEnv *env, jobject obj)
+{
+ jclass clazz = env->GetObjectClass(obj);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ if (!clazz)
+ {
+ throw jau::InternalError("no class found", E_FILE_LINE);
+ }
+ return clazz;
+}
+
+jclass jau::search_class(JNIEnv *env, JavaUplink &object)
+{
+ return search_class(env, object.get_java_class().c_str());
+}
+
+jmethodID jau::search_method(JNIEnv *env, jclass clazz, const char *method_name,
+ const char *prototype, bool is_static)
+{
+ jmethodID method;
+ if (is_static)
+ {
+ method = env->GetStaticMethodID(clazz, method_name, prototype);
+ }
+ else
+ {
+ method = env->GetMethodID(clazz, method_name, prototype);
+ }
+ java_exception_check_and_throw(env, E_FILE_LINE);
+
+ if (!method)
+ {
+ throw jau::InternalError(std::string("no method found: ")+method_name, E_FILE_LINE);
+ }
+
+ return method;
+}
+
+jfieldID jau::search_field(JNIEnv *env, jclass clazz, const char *field_name,
+ const char *type, bool is_static)
+{
+ jfieldID field;
+ if (is_static)
+ {
+ field = env->GetStaticFieldID(clazz, field_name, type);
+ }
+ else
+ {
+ field = env->GetFieldID(clazz, field_name, type);
+ }
+ java_exception_check_and_throw(env, E_FILE_LINE);
+
+ if (!field)
+ {
+ jau::InternalError(std::string("no field found: ")+field_name, E_FILE_LINE);
+ }
+
+ return field;
+}
+
+bool jau::from_jboolean_to_bool(jboolean val)
+{
+ bool result;
+
+ if (val == JNI_TRUE)
+ {
+ result = true;
+ }
+ else
+ {
+ if (val == JNI_FALSE)
+ {
+ result = false;
+ }
+ else
+ {
+ throw jau::InternalError("the jboolean value is not true/false", E_FILE_LINE);
+ }
+ }
+
+ return result;
+}
+
+std::string jau::from_jstring_to_string(JNIEnv *env, jstring str)
+{
+ jboolean is_copy = JNI_TRUE;
+ if (!str) {
+ throw std::invalid_argument("String should not be null");
+ }
+ const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy);
+ if (!str_chars) {
+ throw std::bad_alloc();
+ }
+ const std::string string_to_write = std::string(str_chars);
+
+ env->ReleaseStringUTFChars(str, str_chars);
+
+ return string_to_write;
+}
+
+jstring jau::from_string_to_jstring(JNIEnv *env, const std::string & str)
+{
+ return env->NewStringUTF(str.c_str());
+}
+
+jobject jau::get_new_arraylist(JNIEnv *env, jsize size, jmethodID *add)
+{
+ jclass arraylist_class = search_class(env, "java/util/ArrayList");
+ jmethodID arraylist_ctor = search_method(env, arraylist_class, "<init>", "(I)V", false);
+
+ jobject result = env->NewObject(arraylist_class, arraylist_ctor, size);
+ if (!result)
+ {
+ throw jau::InternalError("Cannot create instance of class ArrayList", E_FILE_LINE);
+ }
+
+ *add = search_method(env, arraylist_class, "add", "(Ljava/lang/Object;)Z", false);
+
+ env->DeleteLocalRef(arraylist_class);
+ return result;
+}
+
+
+//
+// C++ java_anon implementation
+//
+
+JavaGlobalObj::~JavaGlobalObj() noexcept {
+ jobject obj = javaObjectRef.getObject();
+ if( nullptr == obj || nullptr == mNotifyDeleted ) {
+ return;
+ }
+ JNIEnv *env = *jni_env;
+ env->CallVoidMethod(obj, mNotifyDeleted);
+ java_exception_check_and_throw(env, E_FILE_LINE); // would abort() if thrown
+}
+
+//
+// C++ java_anon <-> java access, assuming field "long nativeInstance" and native method 'void checkValid()'
+//
+
+//
+// C++ java_anon <-> java access, all generic
+//
+
diff --git a/java_jni/jni/jau/Clock.cxx b/java_jni/jni/jau/Clock.cxx
new file mode 100644
index 0000000..06afa03
--- /dev/null
+++ b/java_jni/jni/jau/Clock.cxx
@@ -0,0 +1,65 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "org_jau_sys_Clock.h"
+
+#include <cstdint>
+#include <cinttypes>
+
+#include <time.h>
+
+#include <jau/environment.hpp>
+
+#include "jau/jni/helper_jni.hpp"
+
+
+static const int64_t NanoPerMilli = 1000000L;
+static const int64_t MilliPerOne = 1000L;
+
+/**
+ * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html>
+ * <p>
+ * Regarding avoiding kernel via VDSO,
+ * see <http://man7.org/linux/man-pages/man7/vdso.7.html>,
+ * clock_gettime seems to be well supported at least on kernel >= 4.4.
+ * Only bfin and sh are missing, while ia64 seems to be complicated.
+ */
+jlong Java_org_jau_sys_Clock_currentTimeMillis(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ struct timespec t;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ int64_t res = t.tv_sec * MilliPerOne + t.tv_nsec / NanoPerMilli;
+ return (jlong)res;
+}
+
+jlong Java_org_jau_sys_Clock_startupTimeMillisImpl(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ return jau::environment::startupTimeMilliseconds;
+}
+
diff --git a/java_jni/jni/jau/JVM_JNI8.cxx b/java_jni/jni/jau/JVM_JNI8.cxx
new file mode 100644
index 0000000..f6487e8
--- /dev/null
+++ b/java_jni/jni/jau/JVM_JNI8.cxx
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2019 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include <stdio.h> //required by android to identify NULL
+#include <jni.h>
+
+#if defined (JNI_VERSION_1_8)
+
+JNIEXPORT jint JNICALL JNI_OnLoad_jaulib_jni_jni(JavaVM *vm, void *reserved) {
+ (void)vm;
+ (void)reserved;
+ return JNI_VERSION_1_8;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload_jaulib_jni_jni(JavaVM *vm, void *reserved) {
+ (void)vm;
+ (void)reserved;
+}
+
+#endif /* defined (JNI_VERSION_1_8) */
+
diff --git a/java_jni/jni/jau/MachineDataInfoRuntime.cxx b/java_jni/jni/jau/MachineDataInfoRuntime.cxx
new file mode 100644
index 0000000..98ee97a
--- /dev/null
+++ b/java_jni/jni/jau/MachineDataInfoRuntime.cxx
@@ -0,0 +1,211 @@
+
+#include <jni.h>
+
+#include <assert.h>
+
+#include "jau_sys_MachineDataInfoRuntime.h"
+
+#include "jau/jni/helper_jni.hpp"
+
+#if defined(_WIN32)
+ #include <windows.h>
+#else /* assume POSIX sysconf() availability */
+ #include <unistd.h>
+#endif
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getPointerSizeInBytesImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(void *);
+}
+
+JNIEXPORT jlong JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getPageSizeInBytesImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+#if defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return (jlong) si.dwPageSize;
+#else
+ return (jlong) sysconf(_SC_PAGESIZE);
+#endif
+}
+
+typedef struct {
+ int8_t c1;
+ int8_t v;
+} struct_alignment_int8;
+
+typedef struct {
+ int8_t c1;
+ int16_t v;
+} struct_alignment_int16;
+
+typedef struct {
+ int8_t c1;
+ int32_t v;
+} struct_alignment_int32;
+
+typedef struct {
+ int8_t c1;
+ int64_t v;
+} struct_alignment_int64;
+
+typedef struct {
+ int8_t c1;
+ int v;
+} struct_alignment_int;
+
+typedef struct {
+ int8_t c1;
+ long v;
+} struct_alignment_long;
+
+typedef struct {
+ int8_t c1;
+ void * v;
+} struct_alignment_pointer;
+
+typedef struct {
+ int8_t c1;
+ float v;
+} struct_alignment_float;
+
+typedef struct {
+ int8_t c1;
+ double v;
+} struct_alignment_double;
+
+typedef struct {
+ int8_t c1;
+ long double v;
+} struct_alignment_ldouble;
+
+// size_t padding(size_t totalsize, size_t typesize) { return totalsize - typesize - sizeof(char); }
+// static size_t alignment(size_t totalsize, size_t typesize) { return totalsize - typesize; }
+#define ALIGNMENT(a, b) ( (a) - (b) )
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentInt8Impl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_int8 ), sizeof(int8_t));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentInt16Impl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_int16 ), sizeof(int16_t));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentInt32Impl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_int32 ), sizeof(int32_t));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentInt64Impl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_int64 ), sizeof(int64_t));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentIntImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_int ), sizeof(int));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentLongImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_long ), sizeof(long));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentPointerImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_pointer ), sizeof(void *));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentFloatImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_float ), sizeof(float));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentDoubleImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_double ), sizeof(double));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getAlignmentLongDoubleImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return ALIGNMENT(sizeof( struct_alignment_ldouble ), sizeof(long double));
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getSizeOfIntImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(int);
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getSizeOfLongImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(long);
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getSizeOfFloatImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(float);
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getSizeOfDoubleImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(double);
+}
+
+JNIEXPORT jint JNICALL
+Java_jau_sys_MachineDataInfoRuntime_getSizeOfLongDoubleImpl(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ return sizeof(long double);
+}
+
diff --git a/java_jni/jni/jau/UnixDynamicLinkerImpl_JNI.cxx b/java_jni/jni/jau/UnixDynamicLinkerImpl_JNI.cxx
new file mode 100644
index 0000000..9a7a57c
--- /dev/null
+++ b/java_jni/jni/jau/UnixDynamicLinkerImpl_JNI.cxx
@@ -0,0 +1,138 @@
+/* !---- DO NOT EDIT: This file autogenerated by com\sun\gluegen\JavaEmitter.java on Mon Jul 31 16:26:59 PDT 2006 ----! */
+
+#include <jni.h>
+
+#include <assert.h>
+
+#include "jau_sys_dl_UnixDynamicLinkerImpl.h"
+
+ #include <dlfcn.h>
+ #include <inttypes.h>
+
+#ifndef RTLD_DEFAULT
+ #define RTLD_DEFAULT ((void *) 0)
+#endif
+
+// #define DEBUG_DLOPEN 1
+
+#ifdef DEBUG_DLOPEN
+ typedef void *(*DLOPEN_FPTR_TYPE)(const char *filename, int flag);
+ #define VERBOSE_ON 1
+#endif
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #ifdef ANDROID
+ #include <android/log.h>
+ #define DBG_PRINT(...) __android_log_print(ANDROID_LOG_DEBUG, "JogAmp", __VA_ARGS__)
+ #else
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+ #endif
+#else
+ #define DBG_PRINT(...)
+#endif
+
+/*
+ * Class: jau_sys_dl_UnixDynamicLinkerImpl
+ * Method: dlclose
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL
+Java_jau_sys_dl_UnixDynamicLinkerImpl_dlclose(JNIEnv *env, jclass _unused, jlong arg0) {
+ (void)env;
+ (void)_unused;
+
+ int _res;
+ _res = dlclose((void *) (intptr_t) arg0);
+ return _res;
+}
+
+
+/*
+ * Class: jau_sys_dl_UnixDynamicLinkerImpl
+ * Method: dlerror
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_jau_sys_dl_UnixDynamicLinkerImpl_dlerror(JNIEnv *env, jclass _unused) {
+ (void)_unused;
+
+ char * _res;
+ _res = dlerror();
+ if (_res == NULL) return NULL; return env->NewStringUTF(_res);
+}
+
+/*
+ * Class: jau_sys_dl_UnixDynamicLinkerImpl
+ * Method: dlopen
+ * Signature: (Ljava/lang/String;I)J
+ */
+JNIEXPORT jlong JNICALL
+Java_jau_sys_dl_UnixDynamicLinkerImpl_dlopen(JNIEnv *env, jclass _unused, jstring arg0, jint arg1) {
+ (void)_unused;
+
+ const char* _UTF8arg0 = NULL;
+ void * _res;
+#ifdef DEBUG_DLOPEN
+ DLOPEN_FPTR_TYPE dlopenFunc = NULL;
+ DBG_PRINT("XXX dlopen.0\n");
+#endif
+
+ if (arg0 != NULL) {
+ if (arg0 != NULL) {
+ _UTF8arg0 = env->GetStringUTFChars(arg0, (jboolean*)NULL);
+ if (_UTF8arg0 == NULL) {
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
+ "Failed to get UTF-8 chars for argument \"arg0\" in native dispatcher for \"dlopen\"");
+ return 0;
+ }
+ }
+ }
+#ifdef DEBUG_DLOPEN
+ dlopenFunc = (DLOPEN_FPTR_TYPE) dlsym(RTLD_DEFAULT, "dlopen");
+ DBG_PRINT("XXX dlopen.1: lib %s, dlopen-fptr %p %p (%d)\n", _UTF8arg0, dlopen, dlopenFunc, dlopen==dlopenFunc);
+ _res = dlopen((char *) _UTF8arg0, (int) arg1);
+ DBG_PRINT("XXX dlopen.2: %p\n", _res);
+#else
+ _res = dlopen((char *) _UTF8arg0, (int) arg1);
+#endif
+ if (arg0 != NULL) {
+ env->ReleaseStringUTFChars(arg0, _UTF8arg0);
+ }
+#ifdef DEBUG_DLOPEN
+ DBG_PRINT("XXX dlopen.X\n");
+#endif
+ return (jlong) (intptr_t) _res;
+}
+
+/*
+ * Class: jau_sys_dl_UnixDynamicLinkerImpl
+ * Method: dlsym
+ * Signature: (JLjava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL
+Java_jau_sys_dl_UnixDynamicLinkerImpl_dlsym(JNIEnv *env, jclass _unused, jlong arg0, jstring arg1) {
+ (void)_unused;
+
+ const char* _UTF8arg1 = NULL;
+ void * _res;
+ if (arg1 != NULL) {
+ if (arg1 != NULL) {
+ _UTF8arg1 = env->GetStringUTFChars(arg1, (jboolean*)NULL);
+ if (_UTF8arg1 == NULL) {
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
+ "Failed to get UTF-8 chars for argument \"arg1\" in native dispatcher for \"dlsym\"");
+ return 0;
+ }
+ }
+ }
+ _res = dlsym((void *) (intptr_t) arg0, (char *) _UTF8arg1);
+ DBG_PRINT("XXX dlsym: handle %p, symbol %s -> %p\n", (void *) (intptr_t) arg0, _UTF8arg1, _res);
+
+ if (arg1 != NULL) {
+ env->ReleaseStringUTFChars(arg1, _UTF8arg1);
+ }
+ return (jlong) (intptr_t) _res;
+}
+
diff --git a/java_jni/jni/jau/WindowsDynamicLinkerImpl_JNI.cxx b/java_jni/jni/jau/WindowsDynamicLinkerImpl_JNI.cxx
new file mode 100644
index 0000000..f9ee9a7
--- /dev/null
+++ b/java_jni/jni/jau/WindowsDynamicLinkerImpl_JNI.cxx
@@ -0,0 +1,107 @@
+/* !---- DO NOT EDIT: This file autogenerated by com\sun\gluegen\JavaEmitter.java on Tue May 27 02:37:55 PDT 2008 ----! */
+
+#include <jni.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "jau_sys_dl_WindowsDynamicLinkerImpl.h"
+
+ #include <windows.h>
+ /* This typedef is apparently needed for compilers before VC8,
+ and for the embedded ARM compilers we're using */
+ #if !defined(__MINGW64__) && ( (_MSC_VER < 1400) || defined(UNDER_CE) )
+ typedef int intptr_t;
+ #endif
+ /* GetProcAddress doesn't exist in A/W variants under desktop Windows */
+ #ifndef UNDER_CE
+ #define GetProcAddressA GetProcAddress
+ #endif
+
+/* Java->C glue code:
+ * Java package: jogamp.common.os.WindowsDynamicLinkerImpl
+ * Java method: int FreeLibrary(long hLibModule)
+ * C function: BOOL FreeLibrary(HANDLE hLibModule);
+ */
+JNIEXPORT jint JNICALL
+Java_jau_sys_dl_WindowsDynamicLinkerImpl_FreeLibrary(JNIEnv *env, jclass _unused, jlong hLibModule) {
+ (void)env;
+ (void)_unused;
+
+ BOOL _res;
+ _res = FreeLibrary((HANDLE) (intptr_t) hLibModule);
+ return _res;
+}
+
+
+/* Java->C glue code:
+ * Java package: jogamp.common.os.WindowsDynamicLinkerImpl
+ * Java method: int GetLastError()
+ * C function: DWORD GetLastError(void);
+ */
+JNIEXPORT jint JNICALL
+Java_jau_sys_dl_WindowsDynamicLinkerImpl_GetLastError(JNIEnv *env, jclass _unused) {
+ (void)env;
+ (void)_unused;
+
+ DWORD _res;
+ _res = GetLastError();
+ return _res;
+}
+
+
+/* Java->C glue code:
+ * Java package: jogamp.common.os.WindowsDynamicLinkerImpl
+ * Java method: long GetProcAddressA(long hModule, java.lang.String lpProcName)
+ * C function: PROC GetProcAddressA(HANDLE hModule, LPCSTR lpProcName);
+ */
+JNIEXPORT jlong JNICALL
+Java_jau_sys_dl_WindowsDynamicLinkerImpl_GetProcAddressA(JNIEnv *env, jclass _unused, jlong hModule, jstring lpProcName) {
+ (void)_unused;
+
+ const char* _strchars_lpProcName = NULL;
+ PROC _res;
+ if (lpProcName != NULL) {
+ _strchars_lpProcName = env->GetStringUTFChars(lpProcName, (jboolean*)NULL);
+ if (_strchars_lpProcName == NULL) {
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
+ "Failed to get UTF-8 chars for argument \"lpProcName\" in native dispatcher for \"GetProcAddressA\"");
+ return 0;
+ }
+ }
+ _res = GetProcAddressA((HANDLE) (intptr_t) hModule, (LPCSTR) _strchars_lpProcName);
+ if (lpProcName != NULL) {
+ env->ReleaseStringUTFChars(lpProcName, _strchars_lpProcName);
+ }
+ return (jlong) (intptr_t) _res;
+}
+
+
+/* Java->C glue code:
+ * Java package: jogamp.common.os.WindowsDynamicLinkerImpl
+ * Java method: long LoadLibraryW(java.lang.String lpLibFileName)
+ * C function: HANDLE LoadLibraryW(LPCWSTR lpLibFileName);
+ */
+JNIEXPORT jlong JNICALL
+Java_jau_sys_dl_WindowsDynamicLinkerImpl_LoadLibraryW(JNIEnv *env, jclass _unused, jstring lpLibFileName) {
+ (void)_unused;
+
+ jchar* _strchars_lpLibFileName = NULL;
+ HANDLE _res;
+ if (lpLibFileName != NULL) {
+ _strchars_lpLibFileName = (jchar *) calloc(env->GetStringLength(lpLibFileName) + 1, sizeof(jchar));
+ if (_strchars_lpLibFileName == NULL) {
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
+ "Could not allocate temporary buffer for copying string argument \"lpLibFileName\" in native dispatcher for \"LoadLibraryW\"");
+ return 0;
+ }
+ env->GetStringRegion(lpLibFileName, 0, env->GetStringLength(lpLibFileName), _strchars_lpLibFileName);
+ }
+ _res = LoadLibraryW((LPCWSTR) _strchars_lpLibFileName);
+ if (lpLibFileName != NULL) {
+ free((void*) _strchars_lpLibFileName);
+ }
+ return (jlong) (intptr_t) _res;
+}
+
+
diff --git a/java_jni/jni/jni_mem.cxx b/java_jni/jni/jni_mem.cxx
new file mode 100644
index 0000000..981c6e5
--- /dev/null
+++ b/java_jni/jni/jni_mem.cxx
@@ -0,0 +1,169 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Author: Petre Eftime <[email protected]>
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cstdio>
+
+#include <jau/debug.hpp>
+#include <jau/jni/jni_mem.hpp>
+
+JavaVM* vm;
+thread_local JNIEnvContainer jni_env;
+
+jint JNI_OnLoad(JavaVM *initVM, void *reserved) {
+ (void)reserved; // warning
+ vm = initVM;
+ return JNI_VERSION_1_8;
+}
+
+JNIEnv *JNIEnvContainer::operator*() {
+ attach();
+ return env;
+}
+
+JNIEnv *JNIEnvContainer::operator->() {
+ attach();
+ return env;
+}
+
+JNIEnvContainer::JNIEnvContainer() {}
+
+JNIEnvContainer::~JNIEnvContainer() {
+ detach();
+}
+
+void JNIEnvContainer::attach() {
+ if (env != nullptr) {
+ return;
+ }
+ JNIEnv *newEnv = nullptr;
+ int envRes;
+
+ envRes = vm->GetEnv((void **) &env, JNI_VERSION_1_8) ;
+ if( JNI_EDETACHED == envRes ) {
+ envRes = vm->AttachCurrentThreadAsDaemon((void**) &newEnv, NULL);
+ if( JNI_OK != envRes ) {
+ throw jau::RuntimeException("Attach to VM failed", E_FILE_LINE);
+ }
+ env = newEnv;
+ } else if( JNI_OK != envRes ) {
+ throw jau::RuntimeException("GetEnv of VM failed", E_FILE_LINE);
+ }
+ if (env==NULL) {
+ throw jau::RuntimeException("GetEnv of VM is NULL", E_FILE_LINE);
+ }
+ needsDetach = NULL != newEnv;
+}
+
+void JNIEnvContainer::detach() {
+ if (env == nullptr) {
+ return;
+ }
+ if( needsDetach ) {
+ vm->DetachCurrentThread();
+ }
+ env = nullptr;
+ needsDetach = false;
+}
+
+JNIGlobalRef::JNIGlobalRef() noexcept {
+ this->object = nullptr;
+ DBG_JNI_PRINT("JNIGlobalRef::def_ctor nullptr");
+}
+
+JNIGlobalRef::JNIGlobalRef(jobject _object) {
+ if( nullptr == _object ) {
+ throw jau::RuntimeException("JNIGlobalRef ctor null jobject", E_FILE_LINE);
+ }
+ this->object = jni_env->NewGlobalRef(_object);
+ DBG_JNI_PRINT("JNIGlobalRef::def_ctor %p -> %p", _object, this->object);
+}
+
+JNIGlobalRef::JNIGlobalRef(const JNIGlobalRef &o) {
+ if( nullptr == o.object ) {
+ throw jau::RuntimeException("Other JNIGlobalRef jobject is null", E_FILE_LINE);
+ }
+ object = jni_env->NewGlobalRef(o.object);
+ DBG_JNI_PRINT("JNIGlobalRef::copy_ctor %p -> %p", o.object, object);
+}
+JNIGlobalRef::JNIGlobalRef(JNIGlobalRef &&o) noexcept
+: object(o.object) {
+ DBG_JNI_PRINT("JNIGlobalRef::move_ctor %p (nulled) -> %p", o.object, object);
+ o.object = nullptr;
+}
+JNIGlobalRef& JNIGlobalRef::operator=(const JNIGlobalRef &o) {
+ if( &o == this ) {
+ return *this;
+ }
+ JNIEnv * env = *jni_env;
+ if( nullptr != object ) { // always
+ env->DeleteGlobalRef(object);
+ }
+ if( nullptr == o.object ) {
+ throw jau::RuntimeException("Other JNIGlobalRef jobject is null", E_FILE_LINE);
+ }
+ object = jni_env->NewGlobalRef(o.object);
+ DBG_JNI_PRINT("JNIGlobalRef::copy_assign %p -> %p", o.object, object);
+ return *this;
+}
+JNIGlobalRef& JNIGlobalRef::operator=(JNIGlobalRef &&o) noexcept {
+ object = o.object;
+ DBG_JNI_PRINT("JNIGlobalRef::move_assign %p (nulled) -> %p", o.object, object);
+ o.object = nullptr;
+ return *this;
+}
+
+JNIGlobalRef::~JNIGlobalRef() noexcept {
+ try {
+ JNIEnv * env = *jni_env;
+ if( nullptr == env ) {
+ ABORT("JNIGlobalRef dtor null JNIEnv");
+ }
+ DBG_JNI_PRINT("JNIGlobalRef::dtor %p", object);
+ if( nullptr != object ) {
+ // due to move ctor and assignment, we accept nullptr object
+ env->DeleteGlobalRef(object);
+ }
+ } catch (std::exception &e) {
+ fprintf(stderr, "JNIGlobalRef dtor: Caught %s\n", e.what());
+ }
+}
+
+void JNIGlobalRef::clear() noexcept {
+ DBG_JNI_PRINT("JNIGlobalRef::clear %p (nulled) -> null", object);
+ object = nullptr;
+}
+
+bool JNIGlobalRef::operator==(const JNIGlobalRef& rhs) const noexcept {
+ if( &rhs == this ) {
+ DBG_JNI_PRINT("JNIGlobalRef::== true: %p == %p (ptr)", object, rhs.object);
+ return true;
+ }
+ bool res = JNI_TRUE == jni_env->IsSameObject(object, rhs.object);
+ DBG_JNI_PRINT("JNIGlobalRef::== %d: %p == %p (IsSameObject)", res, object, rhs.object);
+ return res;
+}
diff --git a/java_jni/manifest.txt.in b/java_jni/manifest.txt.in
new file mode 100644
index 0000000..7f70c4c
--- /dev/null
+++ b/java_jni/manifest.txt.in
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-Date: @BUILD_TSTAMP@
+Bundle-ManifestVersion: 2
+Bundle-Name: org.jau.sys.dl
+Bundle-SymbolicName: org.jau.sys.dl
+Bundle-Version: @VERSION_SHORT@
+Export-Package: org.jau.sys.dl
+Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.9))"
+Package-Title: org.jau.sys.dl
+Package-Vendor: Gothel Software
+Package-Version: @VERSION_SHORT@
+Specification-Title: Jaulib JNI
+Specification-Vendor: Gothel Software
+Specification-Version: @VERSION_API@
+Implementation-Title: Jaulib JNI
+Implementation-Vendor: Gothel Software
+Implementation-Version: @VERSION@
+Implementation-Commit: @VERSION_SHA1@
+Implementation-URL: http://www.jausoft.com/
+Extension-Name: org.jau.sys.dl
+Trusted-Library: true
+Permissions: all-permissions
+Application-Library-Allowable-Codebase: *
+
+Name: org/jau/sys/dl
+Sealed: false
+
+Name: jau/sys/dl
+Sealed: false
+
diff --git a/java_jni/org/jau/sys/Clock.java b/java_jni/org/jau/sys/Clock.java
new file mode 100644
index 0000000..43beb63
--- /dev/null
+++ b/java_jni/org/jau/sys/Clock.java
@@ -0,0 +1,53 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.jau.sys;
+
+public class Clock {
+ private static long t0;
+ static {
+ t0 = startupTimeMillisImpl();
+ }
+ private static native long startupTimeMillisImpl();
+
+ /**
+ * Returns current monotonic time in milliseconds.
+ */
+ public static native long currentTimeMillis();
+
+ /**
+ * Returns the startup time in monotonic time in milliseconds of the native module.
+ */
+ public static long startupTimeMillis() { return t0; }
+
+ /**
+ * Returns current elapsed monotonic time in milliseconds since module startup, see {@link #startupTimeMillis()}.
+ */
+ public static long elapsedTimeMillis() { return currentTimeMillis() - t0; }
+
+ /**
+ * Returns elapsed monotonic time in milliseconds since module startup comparing against the given timestamp, see {@link #startupTimeMillis()}.
+ */
+ public static long elapsedTimeMillis(final long current_ts) { return current_ts - t0; }
+
+}
diff --git a/java_jni/org/jau/sys/dl/DynamicLibraryBundle.java b/java_jni/org/jau/sys/dl/DynamicLibraryBundle.java
new file mode 100644
index 0000000..6a5eb0b
--- /dev/null
+++ b/java_jni/org/jau/sys/dl/DynamicLibraryBundle.java
@@ -0,0 +1,422 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2010 Gothel Software e.K.
+ * Copyright (c) 2010 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.jau.sys.dl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.jau.sys.JNILibrary;
+import org.jau.util.parallel.RunnableExecutor;
+
+/**
+ * Provides bundling of:<br>
+ * <ul>
+ * <li>The to-be-glued native library, eg OpenGL32.dll. From here on this is referred as the Tool.</li>
+ * <li>The JNI glue-code native library, eg jogl_desktop.dll. From here on this is referred as the Glue</li>
+ * </ul>
+ * <p>
+ * An {@link DynamicLibraryBundleInfo} instance is being passed in the constructor,
+ * providing the required information about the tool and glue libraries.
+ * The ClassLoader of it's implementation is also being used to help locating the native libraries.
+ * </p>
+ * An instance provides a complete {@link com.jogamp.common.os.DynamicLookupHelper}
+ * to {@link com.jogamp.gluegen.runtime.ProcAddressTable#reset(com.jogamp.common.os.DynamicLookupHelper) reset}
+ * the {@link com.jogamp.gluegen.runtime.ProcAddressTable}.<br>
+ * At construction, it:
+ * <ul>
+ * <li> loads the Tool native library via
+ * {@link com.jogamp.common.os.NativeLibrary#open(java.lang.String, java.lang.ClassLoader, boolean) NativeLibrary's open method}</li>
+ * <li> loads the {@link org.jau.sys.JNIJarLibrary.common.jvm.JNILibLoaderBase#loadLibrary(java.lang.String, java.lang.String[], boolean, ClassLoader) Glue native library}</li>
+ * <li> resolves the Tool's {@link com.jogamp.common.os.DynamicLibraryBundleInfo#getToolGetProcAddressFuncNameList() GetProcAddress}. (optional)</li>
+ * </ul>
+ */
+public class DynamicLibraryBundle implements DynamicLookupHelper {
+ private final DynamicLibraryBundleInfo info;
+
+ protected final List<NativeLibrary> nativeLibraries;
+ private final DynamicLinker dynLinkGlobal;
+ private final List<List<String>> toolLibNames;
+ private final List<String> glueLibNames;
+ private final boolean[] toolLibLoaded;
+
+ private int toolLibLoadedNumber;
+
+ private final boolean[] glueLibLoaded;
+ private int glueLibLoadedNumber;
+
+ private long toolGetProcAddressHandle;
+ private boolean toolGetProcAddressComplete;
+ private HashSet<String> toolGetProcAddressFuncNameSet;
+ private final List<String> toolGetProcAddressFuncNameList;
+
+ /** Returns the default {@link RunnableExecutor#currentThreadExecutor}. */
+ public static RunnableExecutor getDefaultRunnableExecutor() {
+ return RunnableExecutor.currentThreadExecutor;
+ }
+
+ /**
+ * Instantiates and loads all {@link NativeLibrary}s incl. JNI libraries.
+ * <p>
+ * The ClassLoader of the {@link DynamicLibraryBundleInfo} implementation class
+ * is being used to help locating the native libraries.
+ * </p>
+ */
+ public DynamicLibraryBundle(final DynamicLibraryBundleInfo info) {
+ if(null==info) {
+ throw new RuntimeException("Null DynamicLibraryBundleInfo");
+ }
+ this.info = info;
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - DynamicLibraryBundle.init start with: "+info.getClass().getName());
+ }
+ nativeLibraries = new ArrayList<NativeLibrary>();
+ toolLibNames = info.getToolLibNames();
+ glueLibNames = info.getGlueLibNames();
+ toolLibLoaded = new boolean[toolLibNames.size()];
+ if(DEBUG) {
+ if( toolLibNames.size() == 0 ) {
+ System.err.println("No Tool native library names given");
+ }
+
+ if( glueLibNames.size() == 0 ) {
+ System.err.println("No Glue native library names given");
+ }
+ }
+
+ for(int i=toolLibNames.size()-1; i>=0; i--) {
+ toolLibLoaded[i] = false;
+ }
+ glueLibLoaded = new boolean[glueLibNames.size()];
+ for(int i=glueLibNames.size()-1; i>=0; i--) {
+ glueLibLoaded[i] = false;
+ }
+
+ {
+ final DynamicLinker[] _dynLinkGlobal = { null };
+ info.getLibLoaderExecutor().invoke(true, new Runnable() {
+ @Override
+ public void run() {
+ _dynLinkGlobal[0] = loadLibraries();
+ } } ) ;
+ dynLinkGlobal = _dynLinkGlobal[0];
+ }
+
+ toolGetProcAddressFuncNameList = info.getToolGetProcAddressFuncNameList();
+ if( null != toolGetProcAddressFuncNameList ) {
+ toolGetProcAddressFuncNameSet = new HashSet<String>(toolGetProcAddressFuncNameList);
+ toolGetProcAddressHandle = getToolGetProcAddressHandle();
+ toolGetProcAddressComplete = 0 != toolGetProcAddressHandle;
+ } else {
+ toolGetProcAddressFuncNameSet = new HashSet<String>();
+ toolGetProcAddressHandle = 0;
+ toolGetProcAddressComplete = true;
+ }
+ if(DEBUG) {
+ System.err.println("DynamicLibraryBundle.init Summary: "+info.getClass().getName());
+ System.err.println(" toolGetProcAddressFuncNameList: "+toolGetProcAddressFuncNameList+", complete: "+toolGetProcAddressComplete+", 0x"+Long.toHexString(toolGetProcAddressHandle));
+ System.err.println(" Tool Lib Names : "+toolLibNames);
+ System.err.println(" Tool Lib Loaded: "+getToolLibLoadedNumber()+"/"+getToolLibNumber()+" "+Arrays.toString(toolLibLoaded)+", complete "+isToolLibComplete());
+ System.err.println(" Glue Lib Names : "+glueLibNames);
+ System.err.println(" Glue Lib Loaded: "+getGlueLibLoadedNumber()+"/"+getGlueLibNumber()+" "+Arrays.toString(glueLibLoaded)+", complete "+isGlueLibComplete());
+ System.err.println(" All Complete: "+isLibComplete());
+ System.err.println(" LibLoaderExecutor: "+info.getLibLoaderExecutor().getClass().getName());
+ }
+ }
+
+ /** Unload all {@link NativeLibrary}s, and remove all references. */
+ public final void destroy() {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - DynamicLibraryBundle.destroy() START: "+info.getClass().getName());
+ }
+ toolGetProcAddressFuncNameSet = null;
+ toolGetProcAddressHandle = 0;
+ toolGetProcAddressComplete = false;
+ for(int i = 0; i<nativeLibraries.size(); i++) {
+ nativeLibraries.get(i).close();
+ }
+ nativeLibraries.clear();
+ toolLibNames.clear();
+ glueLibNames.clear();
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - DynamicLibraryBundle.destroy() END: "+info.getClass().getName());
+ }
+ }
+
+ public final boolean isLibComplete() {
+ return isToolLibComplete() && isGlueLibComplete() ;
+ }
+
+ public final int getToolLibNumber() {
+ return toolLibNames.size();
+ }
+
+ public final int getToolLibLoadedNumber() {
+ return toolLibLoadedNumber;
+ }
+
+ /**
+ * @return true if all tool libraries are loaded,
+ * otherwise false.
+ *
+ * @see DynamicLibraryBundleInfo#getToolLibNames()
+ */
+ public final boolean isToolLibComplete() {
+ final int toolLibNumber = getToolLibNumber();
+ return toolGetProcAddressComplete &&
+ ( 0 == toolLibNumber || null != dynLinkGlobal ) &&
+ toolLibNumber == getToolLibLoadedNumber();
+ }
+
+ public final boolean isToolLibLoaded() {
+ return 0 < toolLibLoadedNumber;
+ }
+
+ public final boolean isToolLibLoaded(final int i) {
+ if(0 <= i && i < toolLibLoaded.length) {
+ return toolLibLoaded[i];
+ }
+ return false;
+ }
+
+ public final int getGlueLibNumber() {
+ return glueLibNames.size();
+ }
+
+ public final int getGlueLibLoadedNumber() {
+ return glueLibLoadedNumber;
+ }
+
+ /**
+ * @return true if the last entry has been loaded,
+ * while ignoring the preload dependencies.
+ * Otherwise false.
+ *
+ * @see DynamicLibraryBundleInfo#getGlueLibNames()
+ */
+ public final boolean isGlueLibComplete() {
+ return 0 == getGlueLibNumber() || isGlueLibLoaded(getGlueLibNumber() - 1);
+ }
+
+ public final boolean isGlueLibLoaded(final int i) {
+ if(0 <= i && i < glueLibLoaded.length) {
+ return glueLibLoaded[i];
+ }
+ return false;
+ }
+
+ public final DynamicLibraryBundleInfo getBundleInfo() { return info; }
+
+ protected final long getToolGetProcAddressHandle() throws SecurityException {
+ if(!isToolLibLoaded()) {
+ return 0;
+ }
+ long aptr = 0;
+ for (int i=0; i < toolGetProcAddressFuncNameList.size(); i++) {
+ final String name = toolGetProcAddressFuncNameList.get(i);
+ aptr = dynamicLookupFunctionOnLibs(name);
+ if(DEBUG) {
+ System.err.println("getToolGetProcAddressHandle: "+name+" -> 0x"+Long.toHexString(aptr));
+ }
+ }
+ return aptr;
+ }
+
+ protected static final NativeLibrary loadFirstAvailable(final List<String> libNames,
+ final boolean searchSystemPath,
+ final boolean searchSystemPathFirst,
+ final ClassLoader loader, final boolean global) throws SecurityException {
+ for (int i=0; i < libNames.size(); i++) {
+ final NativeLibrary lib = NativeLibrary.open(libNames.get(i), searchSystemPath, searchSystemPathFirst, loader, global);
+ if (lib != null) {
+ return lib;
+ }
+ }
+ return null;
+ }
+
+ final DynamicLinker loadLibraries() throws SecurityException {
+ int i;
+ toolLibLoadedNumber = 0;
+ final ClassLoader cl = info.getClass().getClassLoader();
+ NativeLibrary lib = null;
+ DynamicLinker dynLinkGlobal = null;
+
+ for (i=0; i < toolLibNames.size(); i++) {
+ final List<String> libNames = toolLibNames.get(i);
+ if( null != libNames && libNames.size() > 0 ) {
+ lib = loadFirstAvailable(libNames,
+ info.searchToolLibInSystemPath(),
+ info.searchToolLibSystemPathFirst(),
+ cl, info.shallLinkGlobal());
+ if ( null == lib ) {
+ if(DEBUG) {
+ System.err.println("Unable to load any Tool library of: "+libNames);
+ }
+ } else {
+ if( null == dynLinkGlobal ) {
+ dynLinkGlobal = lib.dynamicLinker();
+ }
+ nativeLibraries.add(lib);
+ toolLibLoaded[i]=true;
+ toolLibLoadedNumber++;
+ if(DEBUG) {
+ System.err.println("Loaded Tool library: "+lib);
+ }
+ }
+ }
+ }
+ if( toolLibNames.size() > 0 && !isToolLibLoaded() ) {
+ if(DEBUG) {
+ System.err.println("No Tool libraries loaded");
+ }
+ return dynLinkGlobal;
+ }
+
+ glueLibLoadedNumber = 0;
+ for (i=0; i < glueLibNames.size(); i++) {
+ final String libName = glueLibNames.get(i);
+ final boolean ignoreError = true;
+ boolean res;
+ try {
+ res = JNILibrary.loadLibrary(libName, ignoreError, cl);
+ if(DEBUG && !res) {
+ System.err.println("Info: Could not load JNI/Glue library: "+libName);
+ }
+ } catch (final UnsatisfiedLinkError e) {
+ res = false;
+ if(DEBUG) {
+ System.err.println("Unable to load JNI/Glue library: "+libName);
+ e.printStackTrace();
+ }
+ }
+ glueLibLoaded[i] = res;
+ if(res) {
+ glueLibLoadedNumber++;
+ }
+ }
+
+ return dynLinkGlobal;
+ }
+
+ /**
+ * @param funcName
+ * @return
+ * @throws SecurityException if user is not granted access for the library set.
+ */
+ private final long dynamicLookupFunctionOnLibs(final String funcName) throws SecurityException {
+ if(!isToolLibLoaded() || null==funcName) {
+ if(DEBUG_LOOKUP && !isToolLibLoaded()) {
+ System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** Tool native library not loaded");
+ }
+ return 0;
+ }
+ long addr = 0;
+ NativeLibrary lib = null;
+
+ if( info.shallLookupGlobal() ) {
+ // Try a global symbol lookup first ..
+ // addr = NativeLibrary.dynamicLookupFunctionGlobal(funcName);
+ addr = dynLinkGlobal.lookupSymbolGlobal(funcName);
+ }
+ // Look up this function name in all known libraries
+ for (int i=0; 0==addr && i < nativeLibraries.size(); i++) {
+ lib = nativeLibraries.get(i);
+ addr = lib.dynamicLookupFunction(funcName);
+ }
+ if(DEBUG_LOOKUP) {
+ final String libName = ( null == lib ) ? "GLOBAL" : lib.toString();
+ if(0!=addr) {
+ System.err.println("Lookup-Native: <" + funcName + "> 0x" + Long.toHexString(addr) + " in lib " + libName );
+ } else {
+ System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** in libs " + nativeLibraries);
+ }
+ }
+ return addr;
+ }
+
+ private final long toolDynamicLookupFunction(final String funcName) {
+ if(0 != toolGetProcAddressHandle) {
+ final long addr = info.toolGetProcAddress(toolGetProcAddressHandle, funcName);
+ if(DEBUG_LOOKUP) {
+ if(0!=addr) {
+ System.err.println("Lookup-Tool: <"+funcName+"> 0x"+Long.toHexString(addr)+", via tool 0x"+Long.toHexString(toolGetProcAddressHandle));
+ }
+ }
+ return addr;
+ }
+ return 0;
+ }
+
+ @Override
+ public final void claimAllLinkPermission() throws SecurityException {
+ for (int i=0; i < nativeLibraries.size(); i++) {
+ nativeLibraries.get(i).claimAllLinkPermission();
+ }
+ }
+ @Override
+ public final void releaseAllLinkPermission() throws SecurityException {
+ for (int i=0; i < nativeLibraries.size(); i++) {
+ nativeLibraries.get(i).releaseAllLinkPermission();
+ }
+ }
+
+ @Override
+ public final long dynamicLookupFunction(final String funcName) throws SecurityException {
+ if(!isToolLibLoaded() || null==funcName) {
+ if(DEBUG_LOOKUP && !isToolLibLoaded()) {
+ System.err.println("Lookup: <" + funcName + "> ** FAILED ** Tool native library not loaded");
+ }
+ return 0;
+ }
+
+ if(toolGetProcAddressFuncNameSet.contains(funcName)) {
+ return toolGetProcAddressHandle;
+ }
+
+ long addr = 0;
+ final boolean useToolGetProcAdressFirst = info.useToolGetProcAdressFirst(funcName);
+
+ if(useToolGetProcAdressFirst) {
+ addr = toolDynamicLookupFunction(funcName);
+ }
+ if(0==addr) {
+ addr = dynamicLookupFunctionOnLibs(funcName);
+ }
+ if(0==addr && !useToolGetProcAdressFirst) {
+ addr = toolDynamicLookupFunction(funcName);
+ }
+ return addr;
+ }
+
+ @Override
+ public final boolean isFunctionAvailable(final String funcName) throws SecurityException {
+ return 0 != dynamicLookupFunction(funcName);
+ }
+}
+
diff --git a/java_jni/org/jau/sys/dl/DynamicLibraryBundleInfo.java b/java_jni/org/jau/sys/dl/DynamicLibraryBundleInfo.java
new file mode 100644
index 0000000..a66168f
--- /dev/null
+++ b/java_jni/org/jau/sys/dl/DynamicLibraryBundleInfo.java
@@ -0,0 +1,128 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2010 Gothel Software e.K.
+ * Copyright (c) 2010 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.jau.sys.dl;
+
+import java.util.List;
+
+import org.jau.util.parallel.RunnableExecutor;
+
+public interface DynamicLibraryBundleInfo {
+ public static final boolean DEBUG = DynamicLibraryBundle.DEBUG;
+
+ /**
+ * Returns {@code true} if tool libraries shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
+ * @since 2.4.0
+ */
+ public boolean searchToolLibInSystemPath();
+
+ /**
+ * Returns {@code true} if system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
+ * <p>
+ * If {@link #searchToolLibInSystemPath()} is {@code false} the return value is ignored.
+ * </p>
+ * @since 2.4.0
+ */
+ public boolean searchToolLibSystemPathFirst();
+
+ /**
+ * If a {@link SecurityManager} is installed, user needs link permissions
+ * for the named libraries.
+ *
+ * @return a list of Tool library names or alternative library name lists.<br>
+ * <ul>
+ * <li>GL/GLU example Unix: [ [ "libGL.so.1", "libGL.so", "GL" ], [ "libGLU.so", "GLU" ] ] </li>
+ * <li>GL/GLU example Windows: [ "OpenGL32", "GLU32" ] </li>
+ * <li>Cg/CgGL example: [ [ "libCg.so", "Cg" ], [ "libCgGL.so", "CgGL" ] ] </li>
+ * </pre>
+ */
+ public List<List<String>> getToolLibNames();
+
+ /**
+ * If a {@link SecurityManager} is installed, user needs link permissions
+ * for the named libraries.
+ *
+ * @return a list of Glue library names.<br>
+ * <ul>
+ * <li>GL: [ "nativewindow_x11", "jogl_gl2es12", "jogl_desktop" ] </li>
+ * <li>NEWT: [ "nativewindow_x11", "newt" ] </li>
+ * <li>Cg: [ "nativewindow_x11", "jogl_cg" ] </li>
+ * </ul><br>
+ * Only the last entry is crucial, ie all other are optional preload dependencies and may generate errors,
+ * which are ignored.
+ */
+ public List<String> getGlueLibNames();
+
+ /**
+ * May return the native libraries <pre>GetProcAddressFunc</pre> names, the first found function is being used.<br>
+ * This could be eg: <pre> glXGetProcAddressARB, glXGetProcAddressARB </pre>.<br>
+ * If your Tool does not has this facility, just return null.
+ * @see #toolGetProcAddress(long, String)
+ */
+ public List<String> getToolGetProcAddressFuncNameList() ;
+
+ /**
+ * May implement the lookup function using the Tools facility.<br>
+ * The actual function pointer is provided to allow proper bootstrapping of the ProcAddressTable,
+ * using one of the provided function names by {@link #getToolGetProcAddressFuncNameList()}.<br>
+ */
+ public long toolGetProcAddress(long toolGetProcAddressHandle, String funcName);
+
+ /**
+ * @param funcName
+ * @return true if {@link #toolGetProcAddress(long, String)} shall be tried before
+ * the system loader for the given function lookup. Otherwise false.
+ * Default is <b>true</b>.
+ */
+ public boolean useToolGetProcAdressFirst(String funcName);
+
+ /** @return true if the native library symbols shall be made available for symbol resolution of subsequently loaded libraries. */
+ public boolean shallLinkGlobal();
+
+ /**
+ * If method returns <code>true</code> <i>and</i> if a {@link SecurityManager} is installed, user needs link permissions
+ * for <b>all</b> libraries, i.e. for <code>new RuntimePermission("loadLibrary.*");</code>!
+ *
+ * @return true if the dynamic symbol lookup shall happen system wide, over all loaded libraries.
+ * Otherwise only the loaded native libraries are used for lookup, which shall be the default.
+ */
+ public boolean shallLookupGlobal();
+
+ /**
+ * Returns a suitable {@link RunnableExecutor} implementation, which is being used
+ * to load the <code>tool</code> and <code>glue</code> native libraries.
+ * <p>
+ * This allows the generic {@link DynamicLibraryBundle} implementation to
+ * load the native libraries on a designated thread.
+ * </p>
+ * <p>
+ * An implementation may return {@link DynamicLibraryBundle#getDefaultRunnableExecutor()}.
+ * </p>
+ */
+ public RunnableExecutor getLibLoaderExecutor();
+}
+
+
diff --git a/java_jni/org/jau/sys/dl/DynamicLinker.java b/java_jni/org/jau/sys/dl/DynamicLinker.java
new file mode 100644
index 0000000..2bba77b
--- /dev/null
+++ b/java_jni/org/jau/sys/dl/DynamicLinker.java
@@ -0,0 +1,113 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2013 Gothel Software e.K.
+ * Copyright (c) 2013 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.jau.sys.dl;
+
+/** Low level secure dynamic linker access. */
+public interface DynamicLinker {
+ public static final boolean DEBUG = NativeLibrary.DEBUG;
+ public static final boolean DEBUG_LOOKUP = NativeLibrary.DEBUG_LOOKUP;
+
+ /**
+ * @throws SecurityException if user is not granted global access
+ */
+ public void claimAllLinkPermission() throws SecurityException;
+
+ /**
+ * @throws SecurityException if user is not granted global access
+ */
+ public void releaseAllLinkPermission() throws SecurityException;
+
+ /**
+ * If a {@link SecurityManager} is installed, user needs link permissions
+ * for the named library.
+ * <p>
+ * Opens the named library, allowing system wide access for other <i>users</i>.
+ * </p>
+ *
+ * @param pathname the full pathname for the library to open
+ * @param debug set to true to enable debugging
+ * @return the library handle, maybe 0 if not found.
+ * @throws SecurityException if user is not granted access for the named library.
+ */
+ public long openLibraryGlobal(String pathname, boolean debug) throws SecurityException;
+
+ /**
+ * If a {@link SecurityManager} is installed, user needs link permissions
+ * for the named library.
+ * <p>
+ * Opens the named library, restricting access to this process.
+ * </p>
+ *
+ * @param pathname the full pathname for the library to open
+ * @param debug set to true to enable debugging
+ * @return the library handle, maybe 0 if not found.
+ * @throws SecurityException if user is not granted access for the named library.
+ */
+ public long openLibraryLocal(String pathname, boolean debug) throws SecurityException;
+
+ /**
+ * If a {@link SecurityManager} is installed, user needs link permissions
+ * for <b>all</b> libraries, i.e. for <code>new RuntimePermission("loadLibrary.*");</code>!
+ *
+ * @param symbolName global symbol name to lookup up system wide.
+ * @return the library handle, maybe 0 if not found.
+ * @throws SecurityException if user is not granted access for all libraries.
+ */
+ public long lookupSymbolGlobal(String symbolName) throws SecurityException;
+
+ /**
+ * Security checks are implicit by previous call of
+ * {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}
+ * retrieving the <code>librarHandle</code>.
+ *
+ * @param libraryHandle a library handle previously retrieved via {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}.
+ * @param symbolName global symbol name to lookup up system wide.
+ * @return the library handle, maybe 0 if not found.
+ * @throws IllegalArgumentException in case case <code>libraryHandle</code> is unknown.
+ * @throws SecurityException if user is not granted access for the given library handle
+ */
+ public long lookupSymbol(long libraryHandle, String symbolName) throws SecurityException, IllegalArgumentException;
+
+ /**
+ * Security checks are implicit by previous call of
+ * {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}
+ * retrieving the <code>librarHandle</code>.
+ *
+ * @param libraryHandle a library handle previously retrieved via {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}.
+ * @param debug set to true to enable debugging
+ * @throws IllegalArgumentException in case case <code>libraryHandle</code> is unknown.
+ * @throws SecurityException if user is not granted access for the given library handle
+ */
+ public void closeLibrary(long libraryHandle, boolean debug) throws SecurityException, IllegalArgumentException;
+
+ /**
+ * Returns a string containing the last error.
+ * Maybe called for debuging purposed if any method fails.
+ * @return error string, maybe null. A null or non-null value has no semantics.
+ */
+ public String getLastError();
+}
diff --git a/java_jni/org/jau/sys/dl/DynamicLookupHelper.java b/java_jni/org/jau/sys/dl/DynamicLookupHelper.java
new file mode 100644
index 0000000..4e9a23c
--- /dev/null
+++ b/java_jni/org/jau/sys/dl/DynamicLookupHelper.java
@@ -0,0 +1,57 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Author: Kenneth Bradley Russell
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2011 Gothel Software e.K.
+ * Copyright (c) 2011 JogAmp Community.
+ * Copyright (c) 2003-2005 Sun Microsystems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.jau.sys.dl;
+
+import org.jau.sys.Debug;
+
+public interface DynamicLookupHelper {
+ public static final boolean DEBUG = Debug.debug("NativeLibrary");
+ public static final boolean DEBUG_LOOKUP = Debug.debug("NativeLibrary.Lookup");
+
+ /**
+ * @throws SecurityException if user is not granted access for the library set.
+ */
+ public void claimAllLinkPermission() throws SecurityException;
+ /**
+ * @throws SecurityException if user is not granted access for the library set.
+ */
+ public void releaseAllLinkPermission() throws SecurityException;
+
+ /**
+ * Returns the function handle for function 'funcName'.
+ * @throws SecurityException if user is not granted access for the library set.
+ */
+ public long dynamicLookupFunction(String funcName) throws SecurityException;
+
+ /**
+ * Queries whether function 'funcName' is available.
+ * @throws SecurityException if user is not granted access for the library set.
+ */
+ public boolean isFunctionAvailable(String funcName) throws SecurityException;
+}
diff --git a/java_jni/org/jau/sys/dl/NativeLibrary.java b/java_jni/org/jau/sys/dl/NativeLibrary.java
new file mode 100644
index 0000000..d278b42
--- /dev/null
+++ b/java_jni/org/jau/sys/dl/NativeLibrary.java
@@ -0,0 +1,298 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Author: Kenneth Bradley Russell
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2011 Gothel Software e.K.
+ * Copyright (c) 2011 JogAmp Community.
+ * Copyright (c) 2006 Sun Microsystems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.jau.sys.dl;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.jau.lang.ExceptionUtils;
+import org.jau.sys.JNILibrary;
+import org.jau.sys.PlatformProps;
+
+import jau.sys.dl.BionicDynamicLinker32bitImpl;
+import jau.sys.dl.BionicDynamicLinker64BitImpl;
+import jau.sys.dl.MacOSXDynamicLinkerImpl;
+import jau.sys.dl.PosixDynamicLinkerImpl;
+import jau.sys.dl.WindowsDynamicLinkerImpl;
+
+/** Provides low-level, relatively platform-independent access to
+ shared ("native") libraries. The core library routines
+ <code>System.load()</code> and <code>System.loadLibrary()</code>
+ in general provide suitable functionality for applications using
+ native code, but are not flexible enough to support certain kinds
+ of glue code generation and deployment strategies. This class
+ supports direct linking of native libraries to other shared
+ objects not necessarily installed on the system (in particular,
+ via the use of dlopen(RTLD_GLOBAL) on Unix platforms) as well as
+ manual lookup of function names to support e.g. GlueGen's
+ ProcAddressTable glue code generation style without additional
+ supporting code needed in the generated library. */
+
+public final class NativeLibrary implements DynamicLookupHelper {
+ private final DynamicLinker dynLink;
+
+ // Platform-specific representation for the handle to the open
+ // library. This is an HMODULE on Windows and a void* (the result of
+ // a dlopen() call) on Unix and Mac OS X platforms.
+ private long libraryHandle;
+
+ // May as well keep around the path to the library we opened
+ private final String libraryPath;
+
+ private final boolean global;
+
+ // Private constructor to prevent arbitrary instances from floating around
+ private NativeLibrary(final DynamicLinker dynLink, final long libraryHandle, final String libraryPath, final boolean global) {
+ this.dynLink = dynLink;
+ this.libraryHandle = libraryHandle;
+ this.libraryPath = libraryPath;
+ this.global = global;
+ if (DEBUG) {
+ System.err.println("NativeLibrary.open(): Successfully loaded: " + this);
+ }
+ }
+
+ @Override
+ public final String toString() {
+ return "NativeLibrary[" + dynLink.getClass().getSimpleName() + ", " + libraryPath + ", 0x" + Long.toHexString(libraryHandle) + ", global " + global + "]";
+ }
+
+ /** Opens the given native library, assuming it has the same base
+ name on all platforms.
+ <p>
+ The {@code searchSystemPath} argument changes the behavior to
+ either use the default system path or not at all.
+ </p>
+ <p>
+ Assuming {@code searchSystemPath} is {@code true},
+ the {@code searchSystemPathFirst} argument changes the behavior to first
+ search the default system path rather than searching it last.
+ </p>
+ * @param libName library name, with or without prefix and suffix
+ * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
+ * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
+ * if {@code searchSystemPath} is {@code false} this argument is ignored.
+ * @param loader {@link ClassLoader} to locate the library
+ * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
+ * @return {@link NativeLibrary} instance or {@code null} if library could not be loaded.
+ * @throws SecurityException if user is not granted access for the named library.
+ * @since 2.4.0
+ */
+ public static final NativeLibrary open(final String libName,
+ final boolean searchSystemPath,
+ final boolean searchSystemPathFirst,
+ final ClassLoader loader, final boolean global) throws SecurityException {
+ return open(libName, libName, libName, searchSystemPath, searchSystemPathFirst, loader, global);
+ }
+
+ /** Opens the given native library, assuming it has the given base
+ names (no "lib" prefix or ".dll/.so/.dylib" suffix) on the
+ Windows, Unix and Mac OS X platforms, respectively, and in the
+ context of the specified ClassLoader, which is used to help find
+ the library in the case of e.g. Java Web Start.
+ <p>
+ The {@code searchSystemPath} argument changes the behavior to
+ either use the default system path or not at all.
+ </p>
+ <p>
+ Assuming {@code searchSystemPath} is {@code true},
+ the {@code searchSystemPathFirst} argument changes the behavior to first
+ search the default system path rather than searching it last.
+ </p>
+ Note that we do not currently handle DSO versioning on Unix.
+ Experience with JOAL and OpenAL has shown that it is extremely
+ problematic to rely on a specific .so version (for one thing,
+ ClassLoader.findLibrary on Unix doesn't work with files not
+ ending in .so, for example .so.0), and in general if this
+ dynamic loading facility is used correctly the version number
+ will be irrelevant.
+ * @param libName windows library name, with or without prefix and suffix
+ * @param unixLibName unix library name, with or without prefix and suffix
+ * @param macOSXLibName mac-osx library name, with or without prefix and suffix
+ * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
+ * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
+ * if {@code searchSystemPath} is {@code false} this argument is ignored.
+ * @param loader {@link ClassLoader} to locate the library
+ * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
+ * @return {@link NativeLibrary} instance or {@code null} if library could not be loaded.
+ * @throws SecurityException if user is not granted access for the named library.
+ */
+ public static final NativeLibrary open(final String libName,
+ final String unixLibName,
+ final String macOSXLibName,
+ final boolean searchSystemPath,
+ final boolean searchSystemPathFirst,
+ final ClassLoader loader, final boolean global) throws SecurityException {
+ final List<String> possiblePaths = JNILibrary.enumerateLibraryPaths(libName,
+ unixLibName,
+ macOSXLibName,
+ searchSystemPath, searchSystemPathFirst,
+ loader);
+ PlatformProps.initSingleton(); // loads native gluegen_rt library
+
+ final DynamicLinker dynLink = getDynamicLinker();
+
+ // Iterate down these and see which one if any we can actually find.
+ for (final Iterator<String> iter = possiblePaths.iterator(); iter.hasNext(); ) {
+ final String path = iter.next();
+ if (DEBUG) {
+ System.err.println("NativeLibrary.open(global "+global+"): Trying to load " + path);
+ }
+ long res;
+ Throwable t = null;
+ try {
+ if(global) {
+ res = dynLink.openLibraryGlobal(path, DEBUG);
+ } else {
+ res = dynLink.openLibraryLocal(path, DEBUG);
+ }
+ } catch (final Throwable t1) {
+ t = t1;
+ res = 0;
+ }
+ if ( 0 != res ) {
+ return new NativeLibrary(dynLink, res, path, global);
+ } else if( DEBUG ) {
+ if( null != t ) {
+ System.err.println("NativeLibrary.open: Caught "+t.getClass().getSimpleName()+": "+t.getMessage());
+ }
+ String errstr;
+ try {
+ errstr = dynLink.getLastError();
+ } catch (final Throwable t2) { errstr=null; }
+ System.err.println("NativeLibrary.open: Last error "+errstr);
+ if( null != t ) {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ if (DEBUG) {
+ System.err.println("NativeLibrary.open(global "+global+"): Did not succeed in loading (" + libName + ", " + unixLibName + ", " + macOSXLibName + ")");
+ }
+
+ // For now, just return null to indicate the open operation didn't
+ // succeed (could also throw an exception if we could tell which
+ // of the openLibrary operations actually failed)
+ return null;
+ }
+
+ @Override
+ public final void claimAllLinkPermission() throws SecurityException {
+ dynLink.claimAllLinkPermission();
+ }
+ @Override
+ public final void releaseAllLinkPermission() throws SecurityException {
+ dynLink.releaseAllLinkPermission();
+ }
+
+ @Override
+ public final long dynamicLookupFunction(final String funcName) throws SecurityException {
+ if ( 0 == libraryHandle ) {
+ throw new RuntimeException("Library is not open");
+ }
+ return dynLink.lookupSymbol(libraryHandle, funcName);
+ }
+
+ @Override
+ public final boolean isFunctionAvailable(final String funcName) throws SecurityException {
+ if ( 0 == libraryHandle ) {
+ throw new RuntimeException("Library is not open");
+ }
+ return 0 != dynLink.lookupSymbol(libraryHandle, funcName);
+ }
+
+ /** Looks up the given function name in all loaded libraries.
+ * @throws SecurityException if user is not granted access for the named library.
+ */
+ public final long dynamicLookupFunctionGlobal(final String funcName) throws SecurityException {
+ return dynLink.lookupSymbolGlobal(funcName);
+ }
+
+ /* pp */ final DynamicLinker dynamicLinker() { return dynLink; }
+
+ /* pp */ static DynamicLinker getDynamicLinker() {
+ final DynamicLinker dynLink;
+ switch (PlatformProps.OS) {
+ case WINDOWS:
+ dynLink = new WindowsDynamicLinkerImpl();
+ break;
+
+ case MACOS:
+ case IOS:
+ dynLink = new MacOSXDynamicLinkerImpl();
+ break;
+
+ case ANDROID:
+ if( PlatformProps.CPU.is32Bit ) {
+ dynLink = new BionicDynamicLinker32bitImpl();
+ } else {
+ dynLink = new BionicDynamicLinker64BitImpl();
+ }
+ break;
+
+ default:
+ dynLink = new PosixDynamicLinkerImpl();
+ break;
+ }
+ return dynLink;
+ }
+
+ /** Retrieves the low-level library handle from this NativeLibrary
+ object. On the Windows platform this is an HMODULE, and on Unix
+ and Mac OS X platforms the void* result of calling dlopen(). */
+ public final long getLibraryHandle() {
+ return libraryHandle;
+ }
+
+ /** Retrieves the path under which this library was opened. */
+ public final String getLibraryPath() {
+ return libraryPath;
+ }
+
+ /** Closes this native library. Further lookup operations are not
+ allowed after calling this method.
+ * @throws SecurityException if user is not granted access for the named library.
+ */
+ public final void close() throws SecurityException {
+ if (DEBUG) {
+ System.err.println("NativeLibrary.close(): closing " + this);
+ }
+ if ( 0 == libraryHandle ) {
+ throw new RuntimeException("Library already closed");
+ }
+ final long handle = libraryHandle;
+ libraryHandle = 0;
+ dynLink.closeLibrary(handle, DEBUG);
+ if (DEBUG) {
+ System.err.println("NativeLibrary.close(): Successfully closed " + this);
+ ExceptionUtils.dumpStack(System.err);
+ }
+ }
+}