The missing bridge between Java and native C++

JavaCPP

Gitter Maven Central Sonatype Nexus (Snapshots) Build Status Commercial support: xscode

Introduction

JavaCPP provides efficient access to native C++ inside Java, not unlike the way some C/C++ compilers interact with assembly language. No need to invent new languages such as with SWIG, SIP, C++/CLI, Cython, or RPython. Instead, similar to what cppyy strives to do for Python, it exploits the syntactic and semantic similarities between Java and C++. Under the hood, it uses JNI, so it works with all implementations of Java SE, in addition to Android, Avian, and RoboVM (instructions).

More specifically, when compared to the approaches above or elsewhere (CableSwig, JNIGeneratorApp, cxxwrap, JNIWrapper, Platform Invoke, GlueGen, LWJGL Generator, JNIDirect, ctypes, JNA, JNIEasy, JniMarshall, JNative, J/Invoke, HawtJNI, JNR, BridJ, CFFI, fficxx, CppSharp, cgo, pybind11, rust-bindgen, Panama Native, etc.), it maps naturally and efficiently many common features afforded by the C++ language and often considered problematic, including overloaded operators, class and function templates, callbacks through function pointers, function objects (aka functors), virtual functions and member function pointers, nested struct definitions, variable length arguments, nested namespaces, large data structures containing arbitrary cycles, virtual and multiple inheritance, passing/returning by value/reference/string/vector, anonymous unions, bit fields, exceptions, destructors and shared or unique pointers (via either try-with-resources or garbage collection), and documentation comments. Obviously, neatly supporting the whole of C++ would require more work (although one could argue about the intrinsic neatness of C++), but we are releasing it here as a proof of concept.

As a case in point, we have already used it to produce complete interfaces to OpenCV, FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, ARToolKitPlus, Leptonica, Tesseract, GSL, LLVM, HDF5, MKL, CUDA, Caffe, MXNet, TensorFlow, System APIs, and others as part of the JavaCPP Presets subproject, also demonstrating early parsing capabilities of C/C++ header files that show promising and useful results.

Please feel free to ask questions on the mailing list or the discussion forum if you encounter any problems with the software! I am sure it is far from perfect...

Downloads

Archives containing JAR files are available as releases.

We can also have everything downloaded and installed automatically with:

  • Maven (inside the pom.xml file)
  <dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacpp</artifactId>
    <version>1.5.4</version>
  </dependency>
  • Gradle (inside the build.gradle file)
  dependencies {
    implementation group: 'org.bytedeco', name: 'javacpp', version: '1.5.4'
  }
  • Leiningen (inside the project.clj file)
  :dependencies [
    [org.bytedeco/javacpp "1.5.4"]
  ]
  • sbt (inside the build.sbt file)
  libraryDependencies += "org.bytedeco" % "javacpp" % "1.5.4"

Another option available to Gradle users is Gradle JavaCPP, and similarly for Scala users there is SBT-JavaCPP.

Required Software

To use JavaCPP, you will need to download and install the following software:

To produce binary files for Android 4.0 or newer, you will also have to install:

And similarly to target iOS, you will need to install either:

To modify the source code, please note that the project files were created for:

Finally, because we are dealing with native code, bugs can easily crash the virtual machine. Luckily, the HotSpot VM provides some tools to help us debug under those circumstances:

Getting Started

To understand how JavaCPP is meant to be used, one should first take a look at the Mapping Recipes for C/C++ Libraries, but a high-level overview of the Basic Architecture is also available to understand the bigger picture. The repository of the JavaCPP Presets further provides complex examples that we can use as templates, but it also includes a wiki page on how to Create New Presets that explains their structure in detail along with a small but complete sample project from which one can start experimenting with.

Key Use Cases

To implement native methods, JavaCPP generates appropriate code for JNI, and passes it to the C++ compiler to build a native library. At no point do we need to get our hands dirty with JNI, makefiles, or other native tools. The important thing to realize here is that, while we do all customization inside the Java language using annotations, JavaCPP produces code that has zero overhead compared to manually coded JNI functions (verify the generated .cpp files to convince yourself). Moreover, at runtime, the Loader.load() method automatically loads the native libraries from Java resources, which were placed in the right directory by the building process. They can even be archived in a JAR file, it changes nothing. Users simply do not need to figure out how to make the system load the files. These characteristics make JavaCPP suitable for either

In addition to the few examples provided below, to learn more about how to use the features of this tool, please refer to the Mapping Recipes for C/C++ Libraries as well as the source code of the JavaCPP Presets for examples. For more information about the API itself, one may refer to the documentation generated by Javadoc.

As a matter of course, this all works with the Scala language as well, but to make the process even smoother, it should not be too hard to add support for "native properties", such that declarations like @native var could generate native getter and setter methods...

Accessing Native APIs

The most common use case involves accessing some native library written for C++, for example, inside a file named NativeLibrary.h containing this C++ class:

#include <string>

namespace NativeLibrary {
    class NativeClass {
        public:
            const std::string& get_property() { return property; }
            void set_property(const std::string& property) { this->property = property; }
            std::string property;
    };
}

To get the job done with JavaCPP, we can easily define a Java class such as this one--although one could use the Parser to produce it from the header file as demonstrated by the JavaCPP Presets subproject, following the principles outlined in the Mapping Recipes for C/C++ Libraries:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include="NativeLibrary.h")
@Namespace("NativeLibrary")
public class NativeLibrary {
    public static class NativeClass extends Pointer {
        static { Loader.load(); }
        public NativeClass() { allocate(); }
        private native void allocate();

        // to call the getter and setter functions 
        public native @StdString String get_property(); public native void set_property(String property);

        // to access the member variable directly
        public native @StdString String property();     public native void property(String property);
    }

    public static void main(String[] args) {
        // Pointer objects allocated in Java get deallocated once they become unreachable,
        // but C++ destructors can still be called in a timely fashion with Pointer.deallocate()
        NativeClass l = new NativeClass();
        l.set_property("Hello World!");
        System.out.println(l.property());
    }
}

After compiling the Java source code in the usual way, we also need to build using JavaCPP before executing it, or we can let it do everything as follows:

$ java -jar javacpp.jar NativeLibrary.java -exec
Hello World!

Using Complex C++ Types

To demonstrate its relative ease of use even in the face of complex data types, imagine we had a C++ function that took a vector<vector<void*> > as argument. To support that type, we could define a bare-bones class like this:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include="<vector>")
public class VectorTest {

    @Name("std::vector<std::vector<void*> >")
    public static class PointerVectorVector extends Pointer {
        static { Loader.load(); }
        public PointerVectorVector()       { allocate();  }
        public PointerVectorVector(long n) { allocate(n); }
        public PointerVectorVector(Pointer p) { super(p); } // this = (vector<vector<void*> >*)p
        private native void allocate();                  // this = new vector<vector<void*> >()
        private native void allocate(long n);            // this = new vector<vector<void*> >(n)
        @Name("operator=")
        public native @ByRef PointerVectorVector put(@ByRef PointerVectorVector x);

        @Name("operator[]")
        public native @StdVector PointerPointer get(long n);
        public native @StdVector PointerPointer at(long n);

        public native long size();
        public native @Cast("bool") boolean empty();
        public native void resize(long n);
        public native @Index long size(long i);                   // return (*this)[i].size()
        public native @Index @Cast("bool") boolean empty(long i); // return (*this)[i].empty()
        public native @Index void resize(long i, long n);         // (*this)[i].resize(n)

        public native @Index Pointer get(long i, long j);  // return (*this)[i][j]
        public native void put(long i, long j, Pointer p); // (*this)[i][j] = p
    }

    public static void main(String[] args) {
        PointerVectorVector v = new PointerVectorVector(13);
        v.resize(0, 42); // v[0].resize(42)
        Pointer p = new Pointer() { { address = 0xDEADBEEFL; } };
        v.put(0, 0, p);  // v[0][0] = p

        PointerVectorVector v2 = new PointerVectorVector().put(v);
        Pointer p2 = v2.get(0).get(); // p2 = *(&v[0][0])
        System.out.println(v2.size() + " " + v2.size(0) + "  " + p2);

        v2.at(42);
    }
}

Executing that program using this command produces the following output:

$ java -jar javacpp.jar VectorTest.java -exec
13 42  org.bytedeco.javacpp.Pointer[address=0xdeadbeef,position=0,limit=0,capacity=0,deallocator=null]
Exception in thread "main" java.lang.RuntimeException: vector::_M_range_check: __n (which is 42) >= this->size() (which is 13)
	at VectorTest$PointerVectorVector.at(Native Method)
	at VectorTest.main(VectorTest.java:44)

Optimizing Code Performance

Other times, we may wish to code in C++ (including CUDA) for performance reasons. Suppose our profiler had identified that a method named Processor.process() took 90% of the program's execution time:

public class Processor {
    public static void process(java.nio.Buffer buffer, int size) {
        System.out.println("Processing in Java...");
        // ...
    }

    public static void main(String[] args) {
        process(null, 0);
    }
}

After many days of hard work and sweat, the engineers figured out some hacks and managed to make that ratio drop to 80%, but you know, the managers were still not satisfied. So, we could try to rewrite it in C++ (or even assembly language for that matter via the inline assembler) and place the resulting function in a file named say Processor.h:

#include <iostream>

static inline void process(void *buffer, int size) {
    std::cout << "Processing in C++..." << std::endl;
    // ...
}

After adjusting the Java source code to something like this:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include="Processor.h")
public class Processor {
    static { Loader.load(); }

    public static native void process(java.nio.Buffer buffer, int size);

    public static void main(String[] args) {
        process(null, 0);
    }
}

It would then compile and execute like this:

$ java -jar javacpp.jar Processor.java -exec
Processing in C++...

Creating Callback Functions

Some applications also require a way to call back into the JVM from C/C++, so JavaCPP provides a simple way to define custom callbacks, either as function pointers, function objects, or virtual functions. Although there exist frameworks, which are arguably harder to use, such as Jace, JunC++ion, JCC, jni.hpp, or Scapix that can map complete Java APIs to C++, since invoking a Java method from native code takes at least an order of magnitude more time than the other way around, it does not make much sense in my opinion to export as is an API that was designed to be used in Java. Nevertheless, suppose we want to perform some operations in Java, planning to wrap that into a function named foo() that calls some method inside class Foo, we can write the following code in a file named foo.cpp, taking care to initialize the JVM if necessary with either JavaCPP_init() or by any other means:

#include <iostream>
#include "jniFoo.h"

int main() {
    JavaCPP_init(0, NULL);
    try {
        foo(6, 7);
    } catch (std::exception &e) {
        std::cout << e.what() << std::endl;
    }
    JavaCPP_uninit();
}

We may then declare that function to a call() or apply() method defined in a FunctionPointer as follows:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include="<algorithm>")
@Namespace("std")
public class Foo {
    static { Loader.load(); }

    public static class Callback extends FunctionPointer {
        // Loader.load() and allocate() are required only when explicitly creating an instance
        static { Loader.load(); }
        protected Callback() { allocate(); }
        private native void allocate();

        public @Name("foo") boolean call(int a, int b) throws Exception { 
            throw new Exception("bar " + a * b);
        }
    }

    // We can also pass (or get) a FunctionPointer as argument to (or return value from) other functions
    public static native void stable_sort(IntPointer first, IntPointer last, Callback compare);

    // And to pass (or get) it as a C++ function object, annotate with @ByVal or @ByRef
    public static native void sort(IntPointer first, IntPointer last, @ByVal Callback compare);
}

Since functions also have pointers, we can use FunctionPointer instances accordingly, in ways similar to the FunPtr type of Haskell FFI, but where any java.lang.Throwable object thrown gets translated to std::exception. Building and running this sample code with these commands under Linux x86_64 produces the expected output:

$ java -jar javacpp.jar Foo.java -header
$ g++ -I/usr/lib/jvm/java/include/ -I/usr/lib/jvm/java/include/linux/ foo.cpp linux-x86_64/libjniFoo.so -o foo
$ ./foo
java.lang.Exception: bar 42

In this example, the FunctionPointer object gets created implicitly, but to call a native function pointer, we could define one that instead contains a native call()/apply() method, and create an instance explicitly. Such a class can also be extended in Java to create callbacks, and like any other normal Pointer object, must be allocated with a native void allocate() method, so please remember to hang on to references in Java, as those will get garbage collected. As a bonus, FunctionPointer.call()/apply() maps in fact to an overloaded operator() of a C++ function object that we can pass to other functions by annotating parameters with @ByVal or @ByRef, as with the sort() function in the example above.

It is also possible to do the same thing with virtual functions, whether "pure" or not. Consider the following C++ class defined in a file named Foo.h:

#include <stdio.h>

class Foo {
public:
    int n;
    Foo(int n) : n(n) { }
    virtual ~Foo() { }
    virtual void bar() {
        printf("Callback in C++ (n == %d)\n", n);
    }
};

void callback(Foo *foo) {
    foo->bar();
}

The function Foo::bar() can be overridden in Java if we declare the method in the peer class either as native or abstract and annotate it with @Virtual, for example:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include="Foo.h")
public class VirtualFoo {
    static { Loader.load(); }

    public static class Foo extends Pointer {
        static { Loader.load(); }
        public Foo(int n) { allocate(n); }
        private native void allocate(int n);

        @NoOffset public native int n(); public native Foo n(int n);
        @Virtual  public native void bar();
    }

    public static native void callback(Foo foo);

    public static void main(String[] args) {
        Foo foo = new Foo(13);
        Foo foo2 = new Foo(42) {
            public void bar() {
                System.out.println("Callback in Java (n == " + n() + ")");
            }
        };
        foo.bar();
        foo2.bar();
        callback(foo);
        callback(foo2);
    }
}

Which outputs what one would naturally assume:

$ java -jar javacpp.jar VirtualFoo.java -exec
Callback in C++ (n == 13)
Callback in Java (n == 42)
Callback in C++ (n == 13)
Callback in Java (n == 42)

Instructions for Android, Avian, and RoboVM

The easiest one to get working is Avian compiled with OpenJDK class libraries, so let's start with that. After creating and building a program as described above, without any further modifications, we can directly execute it with this command:

$ /path/to/avian-dynamic -Xbootclasspath/a:javacpp.jar <MainClass>

However, in the case of Android, we need to do a bit more work. For the command line build system based on Ant, inside the directory of the project:

  1. Copy the javacpp.jar file into the libs/ subdirectory, and
  2. Run this command to produce the *.so library files in libs/armeabi/:
$ java -jar libs/javacpp.jar -classpath bin/ -classpath bin/classes/ \
> -properties <android-arm|android-x86> -Dplatform.root=/path/to/android-ndk/ \
> -Dplatform.compiler=/path/to/<arm-linux-androideabi-g++|i686-linux-android-g++> -d libs/<armeabi|x86>/

To make everything automatic, we may also insert that command into the build.xml file. Alternatively, for integration with Android Studio, we can use Gradle JavaCPP.

Similarly for RoboVM, assuming that the compiled classes are in the classes subdirectory:

  1. Copy the javacpp.jar file into the project directory, and
  2. Run the following commands to produce the native binary file:
$ java -jar javacpp.jar -cp classes/ -properties <ios-arm|ios-x86> -o lib
$ /path/to/robovm -arch <thumbv7|x86> -os ios -cp javacpp.jar:classes/ -libs classes/<ios-arm|ios-x86>/lib.o <MainClass>

And instead of Loader.load(), the library should be loaded with System.load("lib.o"), in this case, and might not be required at all.


Project lead: Samuel Audet samuel.audet at gmail.com
Developer site: https://github.com/bytedeco/javacpp
Discussion group: http://groups.google.com/group/javacpp-project

Owner
Bytedeco
Bringing compute-intensive science, multimedia, computer vision, deep learning, etc to the Java platform
Bytedeco
Comments
  • Maven release

    Maven release

    Will it be possible to do a new release of JavaCPP? Last one was on Oct, 2015 and I was hoping to use the latest changes for my project, but I'm inside an environment that doesn't allow to use SNAPSHOT of libraries (so I can't use Sonatype Snapshot).

    Also, have you thought about moving to semantic versioning? (http://semver.org/)

    Thanks

  • [WIP] Add support for Java's module system

    [WIP] Add support for Java's module system

    Overview

    Splits the project into two subprojects: core and maven-plugin. The plugin has dependencies that cannot be modularized, which prevents downstream applications from using jlink to create native runtime images. The core project has no such dependencies, and can be used with jlink

    Loader now looks for property files with absolute paths (/properties/...) instead of relative ones (properties/...)

    Bumps the version to 2.0.0-SNAPSHOT. This might not be necessary, since the artifact name has been changed from javacpp to javacpp-core and javacpp-maven-plugin for the two projects

    How the projects in javacpp-presets will be modularized remains TBD. However, they will also need to be modularized (and moved to different packages) to avoid exporting the org.bytedco.javacpp package from multiple modules

    TODO

    • [ ] Ensure that applications built on Java 9 and above still work; in particular, make sure Loader will still be able to resolve and load native binaries bundled inside the JAR
    • [x] Release a multi-release JAR that can be used by both Java 7 and Java 9 consumers
    • [ ] Update README with instructions for the new artifacts
  • Improve Indexer to allow an hyper-rectangular selection

    Improve Indexer to allow an hyper-rectangular selection

    What about improve the Indexer classes to use the same concert of "hyper-rectangular" selection that HDF5 library is using? See https://portal.hdfgroup.org/display/HDF5/Reading+From+or+Writing+To+a+Subset+of+a+Dataset

  • hello,i have some issue to access on loader.class it maybe cause some particular path or filename

    hello,i have some issue to access on loader.class it maybe cause some particular path or filename

    java.lang.UnsatisfiedLinkError: no jniGen in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:702) at org.bytedeco.javacpp.Loader.load(Loader.java:500) at org.bytedeco.javacpp.Loader.load(Loader.java:417) at org.bytedeco.javacpp.GenICam3.(Gen.java:25) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at org.bytedeco.javacpp.Loader.load(Loader.java:472) at org.bytedeco.javacpp.Loader.load(Loader.java:417) at org.bytedeco.javacpp.Pylon5.(Py.java:41)

  • depthai 2.7.2 led java coredump. But depthai 2.6.0 is fine.

    depthai 2.7.2 led java coredump. But depthai 2.6.0 is fine.

    Environment:

    • OS: Ubuntu 20.04 Desktop 64bit LTS
    • JDK: GraalVM JDK 21.1.0.r11-grl
    • Micronaut 2.5.9
    • JavaCPP: 1.5.6-SNAPSHOT
    • OpenCV: 4.5.3
    • Depthai: 2.7.2
    • test code: depthai-java-test

    Reproduce steps:

    rm -rf ~/.m2/repository/org/bytedeco/*
    rm -rf ~/.javacpp
    cd ~/tmp/
    git clone https://github.com/bytedeco/javacpp-presets
    cd javacpp-presets
    mvn install --projects openblas,opencv,depthai -Djavacpp.platform=linux-x86_64
    cd ~/tmp/
    git clone https://github.com/wureka/depthai-java-test
    cd depthai-java-test
    sh gradlew shadowJar
    java -Djava.library.path=~/tmp/javacpp-presets/depthai/target/native/org/bytedeco/depthai/linux-x86_64:~/tmp/javacpp-presets/openblas/target/native/org/bytedeco/openblas/linux-x86_64:~/tmp/javacpp-presets/opencv/target/native/org/bytedeco/opencv/linux-x86_64 -jar build/libs/depthai-java-test-0.1-all.jar
    

    The actual output is:

    18:29:22.118 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [cli]
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  SIGSEGV (0xb) at pc=0x00007f3512c716e8, pid=704492, tid=704493
    #
    # JRE version: OpenJDK Runtime Environment GraalVM CE 21.1.0 (11.0.11+8) (build 11.0.11+8-jvmci-21.1-b05)
    # Java VM: OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (11.0.11+8-jvmci-21.1-b05, mixed mode, sharing, tiered, jvmci, jvmci compiler, compressed oops, g1 gc, linux-amd64)
    # Problematic frame:
    # C  [libdepthai-core.so+0x1836e8]  tcpip_get_devices+0x148
    #
    # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P %E" (or dumping to /home/alexji/java-projects/depthai-projects/depthai-java-test/core.704492)
    #
    # An error report file with more information is saved as:
    # /home/alexji/java-projects/depthai-projects/depthai-java-test/hs_err_pid704492.log
    #
    # If you would like to submit a bug report, please visit:
    #   https://github.com/oracle/graal/issues
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.
    #
    Aborted (core dumped)
    
    

    If I checkout below code. image

    And modify build.gradle implementation('org.bytedeco:depthai:2.6.0-1.5.6-SNAPSHOT')

    Re-do the above steps. the same code will work. The correct output is:

    17:46:11.664 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [cli]
    Detect 3 camera(s), USB speed: SUPER 
        Camera 0 is ready!
        Camera 1 is ready!
        Camera 2 is ready!
    
    Process finished with exit code 0
    
  • Can any one tell me how to use javacpp in android studio?

    Can any one tell me how to use javacpp in android studio?

    I have spend some time on this, but I just cannot make it work.

    I can't find enough reference material on google. And finally I do it as this: https://www.snip2code.com/Snippet/271596/gradle-build-file-for-JavaCPP

    And I changed it to something like this:

    android.applicationVariants.all { variant ->
        variant.javaCompile.doLast {
            println 'Hello world!'
            javaexec {
                main "org.bytedeco.javacpp.tools.Builder"
                classpath files('path/to/javacpp.jar')
                args '-cp', "variant.javaCompile.destinationDir",
                        '-properties', 'android-arm',
                        '-Dplatform.root', 'path/to/ndk',
                        '-Dplatform.compiler', 'path/to/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++',
                        '-d', 'libs/armeabi'
            }
        }
    }
    

    But the gradle build failed. The error says that 'org.bytedeco.javacpp.tools.builder' not found. And the 'command '/path/to/java'' return nono zero (return 1).

    Can any one helps me. Appreciate!

  • JavaCv Mat to Opencv Mat

    JavaCv Mat to Opencv Mat

    Hi guys

    First of all I would like to apologize to create a label almost similar to Issue #4. I am not a expert in Java as well as c++. However I have been spent last 4 days to take a solution and I got frozen.

    I have rewrite c++ code of Mastering Opencv book , chapter 5, regard Licence plate detecting to java code. But the original c++ code uses filestorage that is not yet implemented in opencv wrapper. So I found FileStorage for javacv (javacPP-presets) that is working fine and can be used to return a CvMat class.

    The issue is the CvMat data should reflect in opencv.Mat instance. But I know they are not compatible and I really dont know how to build a parser to them.

    I tried to run all CvMat data and use "put" method to pass it to opencv.mat. But data got wrong.

    if someone can help with a tip. Source code is really great, but if shows me the way to take would be really helpful.

    thanks in advance

  • Significant performance improvements to Pointer.deallocator

    Significant performance improvements to Pointer.deallocator

    This improves thread contention when locking on the global lock for Pointer allocations in most cases. The global lock can be a performance killer in highly parallel operations, even when memory pressures are not high. In this change we do optimistic provisioning using Atomic operations, and only fall back to locking when there is memory pressure.

    For the totalBytes and the internal linked list this was an easy change. Switching to an AtomicLong and ConcurrentLinkedQueue helps in us being able to do those common actions without needing to lock. The handling of the "PhysicalBytes" however is a bit different in this implementation. We use an AtomicLong to approximate the size based off the internally stored bytes. However on de-allocations this is NOT decremented (while totalBytes is decremented). This means that one of two other methods will need to sync the physicalBytes back to reality. The first (hopefully most likely) would be a sync that occurs every 1000 allocations. The second would be that if we fail to allocate, we will do a trim which will sync this state as well.

    @saudet give me your thoughts on this to resolve #231

    My biggest concerns are around how I am approximating the physical bytes. If there is a better way to estimate the size, or if you think the sync interval needs to be different, let me know. For my use case I could be syncing every million or two. That said, these changes DRAMATICALLY speed up deeplearning4j's kmeans implementation for me.

  • Local repo with include files and libs

    Local repo with include files and libs

    Prototype of the repository we discussed. It is located in ~/.javacpp and has the same structure as Maven's ~/.m2 folder. The build process now packages include files, so that libraries are self-sufficient. E.g. it is not necessary to build native versions of a library's dependencies, and inter-project references to cppbuild/../include and lib can be removed. They are now discovered from the pom definition and fetched to the repo. I only tested on Opencv and Caffe on Linux-64.

  • NullPointerException in Parser and poor Unicode support

    NullPointerException in Parser and poor Unicode support

    With JavaCPP 1.1:

    import org.bytedeco.javacpp.*;
    import org.bytedeco.javacpp.annotation.*;
    
    @Properties(target="org.sqlite.SQLite", value={
    @Platform(include="sqlite3.h")
    })
    public class SQLite {
    }
    
    javac -cp javacpp.jar SQLite.java
    java -jar javacpp.jar SQLite
    
    Targeting org/sqlite/SQLite.java
    Parsing sqlite3.h
    Exception in thread "main" java.lang.NullPointerException
        at org.bytedeco.javacpp.tools.Parser.declarator(Parser.java:913)
        at org.bytedeco.javacpp.tools.Parser.function(Parser.java:1245)
        at org.bytedeco.javacpp.tools.Parser.declarations(Parser.java:2347)
        at org.bytedeco.javacpp.tools.Parser.group(Parser.java:1985)
        at org.bytedeco.javacpp.tools.Parser.declarations(Parser.java:2346)
        at org.bytedeco.javacpp.tools.Parser.extern(Parser.java:2272)
        at org.bytedeco.javacpp.tools.Parser.declarations(Parser.java:2345)
        at org.bytedeco.javacpp.tools.Parser.parse(Parser.java:2421)
        at org.bytedeco.javacpp.tools.Parser.parse(Parser.java:2517)
        at org.bytedeco.javacpp.tools.Builder.parse(Builder.java:67)
        at org.bytedeco.javacpp.tools.Builder.build(Builder.java:624)
        at org.bytedeco.javacpp.tools.Builder.main(Builder.java:773)
    
  • How to use my own compiled library?

    How to use my own compiled library?

    I want use gsl library on my android phone. I've tried the gsl of javacpp-presets but it didn't work. The error said that some .so library did not found. So I want to compile the gsl library myself. I've download the gsl library and do as the gsl presets's cppbuild.sh. The main three line:

    ./configure --prefix=*** .... arm-linux-androideabi-gcc ....
    make -j4
    make install-strip
    

    It works fine. And now I have a gsl library compiled with arm-linux-androideabi-gcc. Now I'm using this C++ code:

    // JavacppDemo.h
    #include "gsl/gsl_sf_bessel.h"
    class Demo {
    public:
        int get() {
            double x = 5.0;
            double y = gsl_sf_bessel_J0(x);
            return (int) y;
        }
    };
    

    And the java code:

    @Platform(include={"JavacppDemo.h"}, link={"gslcblas", "gsl"})
    public class JavacppDemo {
    ****
    }
    

    And I've added the header file path and library path of my newly compiled gsl library to the gradle file. So now I can completely rebuild the project and no errors come out. But when I run it, it says that "could not load library "libgsl.so.19"". I unzip the generated apk file and libgsl.so is not there(only my libjniJavacppDemo.so).

    If I copy the libgsl.so to the armeabi folder, it won't package into the apk file automatically. So how to fix this? Please help me.

  • [SECURITY] Fix Temporary File Information Disclosure Vulnerability

    [SECURITY] Fix Temporary File Information Disclosure Vulnerability

    Security Vulnerability Fix

    This pull request fixes a Temporary File Information Disclosure Vulnerability, which existed in this project.

    Preamble

    The system temporary directory is shared between all users on most unix-like systems (not MacOS, or Windows). Thus, code interacting with the system temporary directory must be careful about file interactions in this directory, and must ensure that the correct file posix permissions are set.

    This PR was generated because a call to File.createTempFile(..) was detected in this repository in a way that makes this project vulnerable to local information disclosure. With the default uname configuration, File.createTempFile(..) creates a file with the permissions -rw-r--r--. This means that any other user on the system can read the contents of this file.

    Impact

    Information in this file is visible to other local users, allowing a malicious actor co-resident on the same machine to view potentially sensitive files.

    Other Examples

    The Fix

    The fix has been to convert the logic above to use the following API that was introduced in Java 1.7.

    File tmpDir = Files.createTempFile("temp dir").toFile();
    

    The API both creates the file securely, ie. with a random, non-conflicting name, with file permissions that only allow the currently executing user to read or write the contents of this file. By default, Files.createTempFile("temp dir") will create a file with the permissions -rw-------, which only allows the user that created the file to view/write the file contents.

    :arrow_right: Vulnerability Disclosure :arrow_left:

    :wave: Vulnerability disclosure is a super important part of the vulnerability handling process and should not be skipped! This may be completely new to you, and that's okay, I'm here to assist!

    First question, do we need to perform vulnerability disclosure? It depends!

    1. Is the vulnerable code only in tests or example code? No disclosure required!
    2. Is the vulnerable code in code shipped to your end users? Vulnerability disclosure is probably required!

    Vulnerability Disclosure How-To

    You have a few options options to perform vulnerability disclosure. However, I'd like to suggest the following 2 options:

    1. Request a CVE number from GitHub by creating a repository-level GitHub Security Advisory. This has the advantage that, if you provide sufficient information, GitHub will automatically generate Dependabot alerts for your downstream consumers, resolving this vulnerability more quickly.
    2. Reach out to the team at Snyk to assist with CVE issuance. They can be reached at the Snyk's Disclosure Email.

    Detecting this and Future Vulnerabilities

    This vulnerability was automatically detected by GitHub's CodeQL using this CodeQL Query.

    You can automatically detect future vulnerabilities like this by enabling the free (for open-source) GitHub Action.

    I'm not an employee of GitHub, I'm simply an open-source security researcher.

    Source

    This contribution was automatically generated with an OpenRewrite refactoring recipe, which was lovingly hand crafted to bring this security fix to your repository.

    The source code that generated this PR can be found here: SecureTempFileCreation

    Opting-Out

    If you'd like to opt-out of future automated security vulnerability fixes like this, please consider adding a file called .github/GH-ROBOTS.txt to your repository with the line:

    User-agent: JLLeitschuh/security-research
    Disallow: *
    

    This bot will respect the ROBOTS.txt format for future contributions.

    Alternatively, if this project is no longer actively maintained, consider archiving the repository.

    CLA Requirements

    This section is only relevant if your project requires contributors to sign a Contributor License Agreement (CLA) for external contributions.

    It is unlikely that I'll be able to directly sign CLAs. However, all contributed commits are already automatically signed-off.

    The meaning of a signoff depends on the project, but it typically certifies that committer has the rights to submit this work under the same license and agrees to a Developer Certificate of Origin (see https://developercertificate.org/ for more information).

    - Git Commit Signoff documentation

    If signing your organization's CLA is a strict-requirement for merging this contribution, please feel free to close this PR.

    Sponsorship & Support

    This contribution is sponsored by HUMAN Security Inc. and the new Dan Kaminsky Fellowship, a fellowship created to celebrate Dan's memory and legacy by funding open-source work that makes the world a better (and more secure) place.

    This PR was generated by Moderne, a free-for-open source SaaS offering that uses format-preserving AST transformations to fix bugs, standardize code style, apply best practices, migrate library versions, and fix common security vulnerabilities at scale.

    Tracking

    All PR's generated as part of this fix are tracked here: https://github.com/JLLeitschuh/security-research/issues/18

  • Using std::variant

    Using std::variant

    Could you please explain how create mapping for std::variant? As I see in changelog it's already supported, but I didn't find an examples of usages in tests or in javacpp-presets. I've added an example class

    class MyVariant {
    public:
        std::variant<
                bool,
                float,
                double> value;
    };
    

    And new class was created automatically, but std::variant was not converted:

    public static class MyVariant extends Pointer {
        static { Loader.load(); }
        /** Default native constructor. */
        public MyVariant() { super((Pointer)null); allocate(); }
        /** Native array allocator. Access with {@link Pointer#position(long)}. */
        public MyVariant(long size) { super((Pointer)null); allocateArray(size); }
        /** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */
        public MyVariant(Pointer p) { super(p); }
        private native void allocate();
        private native void allocateArray(long size);
        @Override public MyVariant position(long position) {
            return (MyVariant)super.position(position);
        }
        @Override public MyVariant getPointer(long i) {
            return new MyVariant((Pointer)this).offsetAddress(i);
        }
    
        public native @ByRef std::variant<bool,float,double> value(); public native MyVariant value(std::variant<bool,float,double> setter);
    }
    
  • Problem with enum with function as a value

    Problem with enum with function as a value

    I've got stuck with such cpp enum:

    enum MyErrorResponse_ErrorCode {
      MyErrorResponse_ErrorCode_kServerError = 0,
      MyErrorResponse_ErrorCode_kOk = 1,
      MyErrorResponse_ErrorCode_ErrorResponse_ErrorCode_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<std::int16_t>::min()
    };
    

    It's parsed to

    public enum MyErrorResponse_ErrorCode {
      MyErrorResponse_ErrorCode_kServerError(0),
      MyErrorResponse_ErrorCode_kOk(1);
      MyErrorResponse_ErrorCode_ErrorResponse_ErrorCode_INT_MIN_SENTINEL_DO_NOT_USE_(MyErrorResponse_ErrorCode_ErrorResponse_ErrorCode_INT_MIN_SENTINEL_DO_NOT_USE_());
    
        public final int value;
        private MyErrorResponse_ErrorCode(int v) { this.value = v; }
        private MyErrorResponse_ErrorCode(MyErrorResponse_ErrorCode e) { this.value = e.value; }
        public MyErrorResponse_ErrorCode intern() { for (MyErrorResponse_ErrorCode e : values()) if (e.value == value) return e; return this; }
        @Override public String toString() { return intern().name(); }
    }
    

    The problem is with MyErrorResponse_ErrorCode_ErrorResponse_ErrorCode_INT_MIN_SENTINEL_DO_NOT_USE_. I've tried to replace std::numeric_limits<std::int16_t>::min() to specific value with javaText or just skip it, but failed. How it can be fixed?

  • The same function pointer set more than 10 times will always pass in a NULL pointer to C/C++

    The same function pointer set more than 10 times will always pass in a NULL pointer to C/C++

    Hi @saudet ,

    As the subject mentioned, I suspect this is a bug. In C, the code is like:

    #include <iostream>
    #include "RpcImpl.h"
    
    using namespace std;
    namespace client {
        rpc_handler_t handler;
    
        void ClientSetMessageHandler(rpc_handler_t userHandler) {
            RPC_INFO("ClientSetMessageHandler userHandler:%p", userHandler);
            handler = userHandler;
        }
    }
    

    In Java/Kotlin we got:

    @RunWith(AndroidJUnit4::class)
    class TestShotSync {
    
        @Test
        fun testFunctionPointer() {
            for (i in 1..20) {
                val handler = ShotSync.rpc_handler_t()
                println("ClientSetMessageHandler No. $i $handler")
                ShotSync.ClientSetMessageHandler(handler)
            }
        }
    }
    

    And after we run the code, the output is like:

    2022-09-29 10:03:55.010 9271-9294 I/System.out: ClientSetMessageHandler No. 1 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433170,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433170,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.011 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1ecdd
    2022-09-29 10:03:55.011 9271-9294 I/System.out: ClientSetMessageHandler No. 2 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433180,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433180,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.011 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f015
    2022-09-29 10:03:55.012 9271-9294 I/System.out: ClientSetMessageHandler No. 3 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433188,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433188,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.012 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f035
    2022-09-29 10:03:55.013 9271-9294 I/System.out: ClientSetMessageHandler No. 4 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433190,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433190,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.013 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f055
    2022-09-29 10:03:55.013 9271-9294 I/System.out: ClientSetMessageHandler No. 5 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433198,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433198,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.013 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f075
    2022-09-29 10:03:55.014 9271-9294 I/System.out: ClientSetMessageHandler No. 6 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331a0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331a0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.014 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f095
    2022-09-29 10:03:55.015 9271-9294 I/System.out: ClientSetMessageHandler No. 7 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331a8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331a8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.015 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f0b5
    2022-09-29 10:03:55.015 9271-9294 I/System.out: ClientSetMessageHandler No. 8 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331b0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331b0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.015 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f0d5
    2022-09-29 10:03:55.016 9271-9294 I/System.out: ClientSetMessageHandler No. 9 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331b8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331b8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.016 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f0f5
    2022-09-29 10:03:55.017 9271-9294 I/System.out: ClientSetMessageHandler No. 10 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331c0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331c0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.017 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0xced1f115
    2022-09-29 10:03:55.018 9271-9294 I/System.out: ClientSetMessageHandler No. 11 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331c8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331c8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.018 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.018 9271-9294 I/System.out: ClientSetMessageHandler No. 12 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331d0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331d0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.018 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.020 9271-9294 I/System.out: ClientSetMessageHandler No. 13 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331d8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331d8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.020 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.020 9271-9294 I/System.out: ClientSetMessageHandler No. 14 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331e0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331e0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.020 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.021 9271-9294 I/System.out: ClientSetMessageHandler No. 15 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331e8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331e8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.021 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.022 9271-9294 I/System.out: ClientSetMessageHandler No. 16 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331f0,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331f0,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.022 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.023 9271-9294 I/System.out: ClientSetMessageHandler No. 17 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe44331f8,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe44331f8,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.023 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.024 9271-9294 I/System.out: ClientSetMessageHandler No. 18 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433200,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433200,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.024 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.025 9271-9294 I/System.out: ClientSetMessageHandler No. 19 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433208,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433208,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.025 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    2022-09-29 10:03:55.026 9271-9294 I/System.out: ClientSetMessageHandler No. 20 com.senter.shotsync.ShotSync$rpc_handler_t[address=0xe4433210,position=0,limit=1,capacity=1,deallocator=org.bytedeco.javacpp.Pointer$NativeDeallocator[ownerAddress=0xe4433210,deallocatorAddress=0xced1f8d1]]
    2022-09-29 10:03:55.026 9271-9294 I/[STC-RPC]: ClientSetMessageHandler userHandler:0x0
    
    

    As we can see, after 10 times of setting the function pointer, we always got a NULL one in C.

    The patch to reproduce it is here.

    Is this because we have only 10 instances of the function pointer in JNI?

  • Race condition in org.bytedeco.javacpp.Loader with multiple JVMs on the same machine

    Race condition in org.bytedeco.javacpp.Loader with multiple JVMs on the same machine

    Hi,

    We recently hit this race condition issue with javacpp.Loader class. The issue happens when you have multiple JVMs running on the same machine, like in Spark.

    It manifests as errors like below when trying to load models using the library.

    Caused by: java.lang.UnsatisfiedLinkError: no jnitensorflow in java.library.path
    	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1875)
    	at java.lang.Runtime.loadLibrary0(Runtime.java:872)
    	at java.lang.System.loadLibrary(System.java:1124)
    	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1738)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1345)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
    	at org.tensorflow.internal.c_api.global.tensorflow.<clinit>(tensorflow.java:12)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:348)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1212)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
    	at org.bytedeco.javacpp.Loader.load(Loader.java:1149)
    	at org.tensorflow.NativeLibrary.load(NativeLibrary.java:48)
    	at org.tensorflow.TensorFlow.<clinit>(TensorFlow.java:140)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:264)
    	at org.tensorflow.Graph.<clinit>(Graph.java:1341)
            ....
    Caused by: java.lang.UnsatisfiedLinkError: /user/home/.javacpp/cache/jarname/org/tensorflow/internal/c_api/linux-x86_64/libjnitensorflow.so: libtensorflow_cc.so.2: cannot open shared object file: No such file or directory
    	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1950)
    	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1832)
    	at java.lang.Runtime.load0(Runtime.java:811)
    	at java.lang.System.load(System.java:1088)
    	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1685)
    	... 104 more
    

    Looking at the Loader code, the file lock only lock within cacheResource method: https://github.com/bytedeco/javacpp/blob/master/src/main/java/org/bytedeco/javacpp/Loader.java#L571-L697 And there are logics like deleting the file within the cacheResource method. (although I still don't understand why it enters into the code block at all if others already cached the file)

                            file.delete();
                            extractResource(resourceURL, file, null, null, true);
                            file.setLastModified(timestamp);
    

    If another JVM on the same machine using the same cacheDir (by default /user/home/.javacpp/cache) try to loadLibrary, it may find the file got deleted by another JVM since there is no file lock here.

Seamless operability between C++11 and Python
Seamless operability between C++11 and Python

pybind11 — Seamless operability between C++11 and Python Setuptools example • Scikit-build example • CMake example Warning Combining older versions of

Nov 25, 2022
Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:

sol2 sol2 is a C++ library binding to Lua. It currently supports all Lua versions 5.1+ (LuaJIT 2.0+ and MoonJIT included). sol2 aims to be easy to use

Nov 25, 2022
Structy is an irresponsibly dumb and simple struct serialization/deserialization library for C, Python, and vanilla JavaScript.

Structy Structy is an irresponsibly dumb and simple struct serialization/deserialization library for C, Python, and vanilla JavaScript. You can think

Sep 13, 2022
Libraries and examples to support Pimoroni Pico add-ons in C++ and MicroPython.

Pimoroni Pico Libraries and Examples Welcome to the brave new world of Pico! This repository contains the C/C++ and MicroPython libraries for our rang

Nov 24, 2022
Tools and libraries to glue C/C++ APIs to high-level languages

CppSharp is a tool and set of libraries which facilitates the usage of native C/C++ code with the .NET ecosystem. It consumes C/C++ header and library

Nov 23, 2022
A tool for generating cross-language type declarations and interface bindings.

Djinni Djinni is a tool for generating cross-language type declarations and interface bindings. It's designed to connect C++ with either Java or Objec

Nov 19, 2022
Duktape - embeddable Javascript engine with a focus on portability and compact footprint

Duktape ⚠️ Master branch is undergoing incompatible changes for Duktape 3.x. To track Duktape 2.x, follow the v2-maintenance branch. Introduction Dukt

Nov 16, 2022
SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages.

SWIG (Simplified Wrapper and Interface Generator) Version: 4.1.0 (in progress) Tagline: SWIG is a compiler that integrates C and C++ with languages

Nov 25, 2022
A minimalist and mundane scripting language.

Drift Script A minimalist and mundane scripting language. I like all simple things, simple and beautiful, simple and strong. I know that all developme

Nov 14, 2022
sc-ble-bridge is a utility that for every connected Steam Controller creates a virtual one acting as a bridge between SC and Steam

sc-ble-bridge The main goal of this utility is to provide workaround for steam-for-linux issue which makes Valve's Steam Controller unusable in BLE mo

Apr 19, 2022
Pico-uart-bridge - Raspberry Pi Pico UART-USB bridge

Raspberry Pi Pico USB-UART Bridge This program bridges the Raspberry Pi Pico HW UARTs to two independent USB CDC serial devices in order to behave lik

Nov 25, 2022
✔️The smallest header-only GUI library(4 KLOC) for all platforms
✔️The smallest header-only GUI library(4 KLOC) for all platforms

Welcome to GUI-lite The smallest header-only GUI library (4 KLOC) for all platforms. 中文 Lightweight ✂️ Small: 4,000+ lines of C++ code, zero dependenc

Nov 24, 2022
Another try to re-create Project Astoria , or some bridge between A and W...

Bridge 1.0.10.0 Forked from: https://github.com/DroidOnUWP/Bridge Abstract Another "Project Astoria" remake (UWP) Original status: Forgotten (?) My ac

Nov 15, 2022
This calculator attempts to bridge the gap between qualitative and quantitative data in societal interactions
This calculator attempts to bridge the gap between qualitative and quantitative data in societal interactions

This calculator attempts to bridge the gap between qualitative and quantitative data in societal interactions. This will help you determine how long you should take before replying to a message from a friend/acquaintance. Use these calculations at your own risk.

Jan 20, 2022
Simple hook that prevent to halt Java Virtual Machine (mostly used in hacking java programs)
Simple hook that prevent to halt Java Virtual Machine (mostly used in hacking java programs)

JavaExitHook Simple hook that prevent to halt Java Virtual Machine (mostly used in hacking java programs) What is used for? Idea to create that simple

Nov 11, 2022
Inter-process communication library to enable allocation between processes/threads and send/receive of allocated regions between producers/consumer processes or threads using this ipc buffer.

This is a relatively simple IPC buffer that allows multiple processes and threads to share a dynamic heap allocator, designate "channels" between processes, and share that memory between producer/consumer pairs on those channels.

Aug 20, 2022
⛵ The missing small and fast image decoding library for humans (not for machines).
⛵ The missing small and fast image decoding library for humans (not for machines).

Squirrel Abstract Image Library The missing fast and easy-to-use image decoding library for humans (not for machines). Target Audience • Features • Im

Nov 14, 2022
This is example for coding with Kotlin/Native, linking C libraries and comparison java.net.* with libcurl

KotlinNativeExample This is example for coding with Kotlin/Native, linking C libraries and comparison java.net.* with libcurl Running Running mingw64

Jan 22, 2022
All the missing SQLite functions

SQLite Plus: all the missing SQLite functions SQLite has very few functions compared to other DBMS. SQLite authors see this as a feature rather than a

Nov 21, 2022
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

Nov 25, 2022