{"id":21944981,"url":"https://github.com/alexanderschuetz97/javanativeutils","last_synced_at":"2025-04-22T21:11:18.436Z","repository":{"id":57732312,"uuid":"435597449","full_name":"AlexanderSchuetz97/JavaNativeUtils","owner":"AlexanderSchuetz97","description":"Collection of jni wrappers for various native system calls","archived":false,"fork":false,"pushed_at":"2024-12-12T23:56:22.000Z","size":42862,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T18:51:15.480Z","etag":null,"topics":["java","jni"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexanderSchuetz97.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-06T18:03:45.000Z","updated_at":"2024-12-12T23:56:26.000Z","dependencies_parsed_at":"2023-01-22T22:45:13.344Z","dependency_job_id":"8dfa4d1e-b900-4d92-b1cd-5e92455ce51b","html_url":"https://github.com/AlexanderSchuetz97/JavaNativeUtils","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderSchuetz97%2FJavaNativeUtils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderSchuetz97%2FJavaNativeUtils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderSchuetz97%2FJavaNativeUtils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderSchuetz97%2FJavaNativeUtils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexanderSchuetz97","download_url":"https://codeload.github.com/AlexanderSchuetz97/JavaNativeUtils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250324697,"owners_count":21411946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","jni"],"created_at":"2024-11-29T04:17:31.850Z","updated_at":"2025-04-22T21:11:18.416Z","avatar_url":"https://github.com/AlexanderSchuetz97.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"l# JavaNativeUtils\nJavaNativeUtils is a library containing a jni wrapper for various operating system specific syscalls.\nPurpose of this library is to allow for direct interaction with the operating system from Java \nwithout having to write a JNI wrapper every single time.\n\n\n## License\nJavaNativeUtils is released under the GNU Lesser General Public License Version 3. \u003cbr\u003e\nA copy of the GNU Lesser General Public License Version 3 can be found in the COPYING \u0026 COPYING.LESSER files.\u003cbr\u003e\n\n## Usage\nMaven:\n````\n\u003cdependency\u003e\n    \u003cgroupId\u003eeu.aschuetz\u003c/groupId\u003e\n    \u003cartifactId\u003eJavaNativeUtilsApi\u003c/artifactId\u003e\n    \u003cversion\u003e4.8\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003eeu.aschuetz\u003c/groupId\u003e\n    \u003cartifactId\u003eJavaNativeUtilsJni\u003c/artifactId\u003e\n    \u003cversion\u003e4.8\u003c/version\u003e\n\u003c/dependency\u003e\n````\nNote: for versions older than 4.0 use groupId io.github.alexanderschuetz97 artifactId JavaNativeUtils\n\nJava:\n````\nif (NativeUtils.isLinux()) {\n    LinuxNativeUtil util = NativeUtils.getLinuxUtil()\n    System.out.println(util.stat(\"/tmp\"));\n    return;\n}\n\nif (NativeUtils.isWindows()) {\n    WindowsNativeUtil util = NativeUtils.getWindowsUtil()\n    System.out.println(util._stat64(\"C:\\\\Windows\"));\n    return;\n}\n\nif (NativeUtils.isMacOS()) {\n    MacOSNativeUtil util = NativeUtils.getMacOSUtil()\n    System.out.println(util.stat(\"/tmp\"));\n    return;\n}\n\nif (NativeUtils.isFreeBSD()) {\n    FreeBSDNativeUtil util = NativeUtils.getFreeBSDUtil()\n    System.out.println(util.stat(\"/tmp\"));\n    return;\n}\n\nif (NativeUtils.isNetBSD()) {\n    NetBSDNativeUtil util = NativeUtils.getNetBSDUtil()\n    System.out.println(util.stat(\"/tmp\"));\n    return;\n}\n\nif (NativeUtils.isOpenBSD()) {\n    OpenBSDNativeUtil util = NativeUtils.getOpenBSDUtil()\n    System.out.println(util.stat(\"/tmp\"));\n    return;\n}\n\n````\n\n## List of supported Syscalls\n#### Linux\n* malloc \u0026 free\n* open\n* fcntl\n* ioctl\n* symlink\n* link\n* unlink\n* stat\n* statvfs\n* fstat\n* lstat\n* chdir\n* strerror_r\n* socket\n* connect\n* read\n* write\n* fsync\n* getsockopt\n* setsockopt\n* close\n* recvfrom\n* recvmsg (includes CMSG HDR parsing)\n* sendmsg\n* mmap\n* msync\n* munmap\n* mkfifo\n* getpagesize\n* __get_cpuid_count (from cpuid.h)\n* if_nametoindex\n* if_indextoname\n* sem_open\n* sem_close\n* sem_unlink\n* sem_init\n* sem_destroy\n* sem_post\n* sem_wait\n* sem_getvalue\n* sem_trywait\n* sem_timedwait\n* shm_open\n* shm_unlink\n* ftruncate\n* truncate\n* memfd_create\n* malloc_trim (only glibc)\n* madvise\n* pthread_condattr_destroy\n* pthread_condattr_init\n* pthread_mutexattr_destroy\n* pthread_mutexattr_init\n* pthread_condattr_getpshared\n* pthread_condattr_setpshared\n* pthread_mutexattr_setpshared\n* pthread_mutexattr_getpshared\n* pthread_mutexattr_settype\n* pthread_mutexattr_gettype\n* pthread_mutexattr_getrobust\n* pthread_mutexattr_setrobust\n* pthread_mutex_consistent\n* pthread_mutex_init\n* pthread_mutex_destroy\n* pthread_mutex_lock\n* pthread_mutex_trylock\n* pthread_mutex_unlock\n* pthread_mutex_timedlock\n* pthread_cond_broadcast\n* pthread_cond_signal\n* pthread_cond_wait\n* pthread_cond_timedwait\n* pthread_cond_destroy\n* pthread_cond_init\n\n#### Windows\n* malloc \u0026 free\n* _locking\n* _stat64\n* LockFileEx\n* UnlockFileEx\n* GetFileAttributesEx\n* CreateSymbolicLinkA\n* CreateHardLinkA\n* CreateFileA\n* CloseHandle\n* GetFileAttributesA\n* SetFileAttributesA\n* ExpandEnvironmentStringsA\n* SetEnvironmentVariableA\n* GetEnvironmentVariableA\n* GetModuleFileNameA\n* GetVolumePathNameW\n* strerror_s\n* FormatMessageA\n* SetupDiGetClassDevsA\n* SetupDiEnumDeviceInterfaces\n* SetupDiGetDeviceInterfaceDetail\n* SetupDiDestroyDeviceInfoList\n* DeviceIoControl\n* CreateEventA\n* OpenEventA\n* ResetEvent\n* SetEvent\n* WaitForSingleObject\n* WaitForMultipleObjects\n* GetOverlappedResult\n* GetFriendlyIfIndex\n* GetAdapterIndex\n* GetAdaptersAddresses\n* GetCurrentThread\n* GetCurrentProcess\n* DuplicateHandle\n* CancelIo\n* CancelIoEx\n* CancelSynchronousIo\n* __get_cpuid_count (from cpuid.h)\n* RegOpenKeyExA\n* RegCloseKey\n* RegQueryValueExA\n* GetTokenInformation\n* OpenProcessToken\n* ShellExecuteA\n* CreateFileMappingA\n* OpenFileMappingA\n* MapViewOfFileEx\n* UnmapViewOfFile\n* GetIpForwardTable2\n* CreateIpForwardEntry2\n* ConvertInterfaceIndexToLuid\n* ConvertInterfaceLuidToIndex\n* ConvertInterfaceLuidToNameA\n* ConvertInterfaceNameToLuidA\n* ConvertInterfaceLuidToAlias\n* CreateNamedPipeA\n* ConnectNamedPipe\n* WaitNamedPipeA\n* DisconnectNamedPipe\n* FlushFileBuffers\n* ReleaseSemaphore\n* CreateSemaphoreExA\n* SetupComm\n* SetCommTimeouts\n* WaitCommEvent\n* TransmitCommChar\n* SetDefaultCommConfigA\n* SetCommState\n* SetCommMask\n* SetCommConfig\n* SetCommBreak\n* PurgeComm\n* GetDefaultCommConfigA\n* GetCommTimeouts\n* GetCommState\n* GetCommProperties\n* GetCommModemStatus\n* GetCommMask\n* GetCommConfig\n* EscapeCommFunction\n* ClearCommError\n* ClearCommBreak\n\n#### FreeBSD \u0026 NetBSD \u0026 OpenBSD \u0026 MacOS\n* malloc \u0026 free\n* __get_cpuid_count (from cpuid.h)\n* stat\n* open\n* close\n* read\n* write\n* lseek\n* mmap\n* msync\n* munmap\n* symlink\n* unlink\n* uname\n\n### List of exposed JNI Functions (All OS)\n### Reflection\nReason: In newer Java Versions (17+) Reflection was gutted and is no longer able to access private Fields. \u003cbr\u003e\nAll those methods are also available in sun.misc.Unsafe. \u003cbr\u003e\nAccessing sun.misc.Unsafe is also non-trivial in newer Java Versions depending on how your application/library is deployed/used.\n\n(X) is a substitute for this set \"Object, Long, Int, Short, Char, Byte, Float, Double\"\n\n* FromReflectedField\n* GetFieldID\n* Get(X)Field\n* GetStatic(X)Field\n* Set(X)Field\n* SetStatic(X)Field\n* FromReflectedMethod\n* GetMethodID\n* GetStaticMethodID\n* Call(X)Method\n* CallStatic(X)Method\n### Other JNI Methods\n* AllocObject\n* DefineClass\n* MonitorEnter\n* MonitorExit\n* Throw\n* NewGlobalRef\n* DeleteGlobalRef\n* NewLocalRef\n* NewDirectByteBuffer\n* GetDirectBufferAddress\n\n\n## Dependencies\n* Java 7 or newer\n\n### Supported Operating Systems / Architectures\n#### Windows (Vista or newer)\n* i386 \n* amd64\n\nOnly amd64 architecture is tested!\n\n#### Linux\n\nGLIBC 2.17 or newer:\n* i386\n* amd64\n* armel\n* armhf\n* aarch64\n* riscv64\n* mips64el\n* ppc64le\n* s390x\n\nmusl libc (Alpine Linux):\n* amd64\n\nOnly amd64 i386 armhf aarch64 and riscv64 architecture is tested with real hardware!\nThe others are only tested using qemu usermode emulation.\n\n#### FreeBSD (14.1)\n* amd64\n\nI currently use freebsd 14.1 to cross compile and test. \nThe library may or may not work with earlier or later versions of freebsd.\n\n#### NetBSD (10.0)\n* amd64\n\nI currently use netbsd 10.0 to cross compile and test.\nThe library may or may not work with earlier or later versions of netbsd.\n\n#### OpenBSD (7.5)\n* amd64\n\nI currently use openbsd 7.5 to cross compile and test.\nThe library may or may not work with earlier or later versions of openbsd.\n\n### MacOS\n* amd64\n\nI currently use zig cc version 0.13 to cross compile and test on MacOS Ventura,\nThe library may or may not work with earlier or later versions of MacOS.\nFor more information see the manual page of the zig cc linker.\n\n### Unsupported OS\n\nIf an unsupported operating system or processor architecture is used then getWindowsUtil() getLinuxUtil() or others throw an exception.\nTo check if the current system supports linux or windows syscalls use the isLinux() isWindows() method.\n\n### INFO: Linux using pthread_mutex and pthread_cond for IPC with a C Program\nNote that pthread_mutex and pthread_cond in shared memory for IPC with a C program will only work\nif the C Program uses the same or a similar enough version of the C library.\n\nThis means that if you use JavaNativeUtils with a glibc jvm to perform IPC with a\nC program that was statically compiled against libc-musl then pthread_mutex\npthread_cond will not be compatible.\n\nIf the C Program uses glibc then it may not use a glibc version older than 2.3.2 (released ~2003) \nif you intend to use pthread_cond. pthread_mutex \"should\" always work.\n\nPlease keep in mind that glibc may decide to \"change\" pthread_cond or pthread_mutex in a future release.\nShould this happen, then the C Program must not be linked against that new version if you want to do IPC communication with it.\nThe build environment for JavaNativeUtils will always use glibc version 2.2.5 for pthread_mutex and\nglibc version 2.3.2 for pthread_cond.\n\nAll information regarding glibc versions was only verified for the amd64 architecture. If you\nintend to use the other architectures then you will have to use objdump to verify that\nthe symbols for pthread_cond and pthread_mutex are the same on the c program and the respective shared object file\nof JavaNativeUtils.\n\n\n## Building and Development\n#### Windows:\nBuilding JavaNativeUtils on Windows natively is not possible.\nYou may have some luck using WSL2, however building in for example a Debian VM is probably\na more useful way to spend your time compared getting docker+qemu+binfmt_misc to work in WSL2.\n\n#### Linux:\nRequirements:\n* bash\n* docker\n* docker-compose\n* jdk 8\n  * Note: for various reasons you must use a JDK 8 to compile... \n  * The compiled library will work when used by any java version between including java 7 and including java 21.\n\nBuilding for the first time will build the docker image to compile the native libraries. \nThis will take a few minutes depending on your internet connection speed. You will only have to do this once\nunless you delete/remove the containers/images.\n\nTo build:\n1. clone the git repository\n2. run:\n````\nmaven -Dmaven.test.skip=true -Dgpg.skip clean install\n````\n\n### How to run foreign architecture tests using QEMU+docker+binfmt_misc\nTo run non amd64 tests you may use the run bash script dockertest.sh in the repository root.\n1. build the entire project and run amd64 tests (clean install)\n2. install qemu-user-static so that for example /usr/bin/qemu-riscv64-static exists, repeat for all architectures\n3. setup binfmt_misc so that the linux kernel knows how to execute elf binaries of foreign architecture \n   - ls /proc/sys/fs/binfmt_misc/ should contain 1 qemu file per architecture\n4. configure your docker daemon to allow foreign architectures\n   - \"docker run --rm -it arm64v8/debian:bookworm\" is a good way to test this.\n5. run dockertest.sh (exit code 0 = no error)\n\n### How to debug the native part\n1. Edit the makefile and uncomment `#DEBUG_FLAGS=-ggdb -g3` and comment the `DEBUG_FLAGS=-g0` line underneath.\n2. Start the jvm with gdbserver and a java remote debugger in attach mode, suspend=y is recommended.\n3. Connect your native remote debugger (I use CLion)\n4. Place a java breakpoint in a java IDE (Eclipse or IntelliJ will work) after the call to System.load in NativeLibraryLoaderHelper\n5. Connect your java remote debugger\n6. You might have to instruct gdb to NOT stop on SIGSEGV and possibly other signals too as the JVM uses this signal internally for garbage collection\n7. Wait until the java breakpoint is hit\n8. Your should now be able to place your native breakpoints in the native debugger as the shared object should now have been loaded.\n9. Hit resume in your java debugger. After this you can detatch the java debugger.\n10. Wait until your native breakpoints are hit.\n\n#### Further debugging tips\n\nYou can preempt NativeLibraryLoaderHelper by calling System.load to your debug so/dll before the first\nusage of NativeUtils in your program. This allows for easy debugging of the native part without\nrecompiling your program with a custom .jar of JavaNativeUtils. This is especially useful if you \ncannot compile JavaNativeUtils locally for whatever reason, since you can just compile a debug so/dll\nin a Virtual Machine and just \"move\" a single shared object file to your actual development machine.\n\nFor debugging the windows native part I use gdbserver.exe to start the jvm. It should also be possible to attach \nproprietary debuggers on windows or build a PDB for them by adjusting the makefile \nand building a custom debug dll manually. I have never compiled JavaNativeUtils with anything \nother than Clang or GCC, using for example the MSVC may work, \nbut will probably require significant modification of the makefile.\n\n## Will this library be obsoleted by the Java FFI Interface (Project Panama)\nProbably yes. The Java FFI Interface allows a Java developer to perform most of the actions\nthat this library permits without writing C code. The only exception would be bypassing the \"Reflection\" checks. \nIt will however require a significant amount of Java code to be written by the developer \nto perform the same things this library does. \nThe main advantage of the FFI Interface vs this library is probably going to be that it can work with any .dll/.so file\nand on any CPU architecture.\n\nMy conclusion from looking at early benchmarks of the Java FFI Interface vs JNI is that the FFI interface\nappears to be somewhat slower than JNI.\n\nIn addition to that, the FFI Interface is still a \"preview\" feature in Java 21 (LTS) and therefore not enabled by\ndefault. A lot of applications still rely on java 8, and I personally doubt that java 8, 11 and 17 (even 21)\nwill disappear in the next 10 years. Just for those versions alone I intend to keep working on this library.\nI also do not expect major adoption of the first LTS release after 21 that will presumably contain the \"full\" FFI \nto happen in the next 6 years.\n\n## Future work\nThis is just a list of things I am considering working on.\nI make no promises as to when or if I will be able to implement them.\n\n#### Split the JNI native libraries into separate dependencies.\nSome of the shared objects contained within this library are relatively large and probably do not see much use.\nIt would probably be a good idea to move those to their own dependency so that each java project can only include\nwhat it actually uses in its bom/assembly.\n\n#### Windows aarch64\nI am considering adding aarch64 support for windows.\n\n#### Write an additional implementation of this library that uses the Java FFI interface\nI am considering to write an additional implementation of JavaNativeUtils\nthat uses the Java FFI Interface instead of shared objects loaded via JNI to \nachieve \"most\" tasks. There will be no implementation of the JVMNativeUtils as those\nfunctions are not provided by the Java FFI Interface.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderschuetz97%2Fjavanativeutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexanderschuetz97%2Fjavanativeutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderschuetz97%2Fjavanativeutils/lists"}