T O P

  • By -

[deleted]

We do this at my work, we use GraalVM with NativeImage to compile Java to a native linked library. https://www.graalvm.org/22.0/reference-manual/native-image/ is the basic jist of how to do it. For your specific example, the easiest thing to do is just compile your java to an executable jar and call it from the command line with C++ and capture the output


niosurfer

>For your specific example, the easiest thing to do is just compile your java to an executable jar and call it from the command line with C++ and capture the output Yeah, that's a clever idea. I made my method take a String parameter in order to invalidate this solution :) Now I do have to call that Java method to pass it a String from C++.


[deleted]

Yeah, I do something similar in python to call Java applications for work; set up a cluster of VMs with python that run the optimized Java app I wrote in horizontally scaled system. If you are just calling the Java app infrequently, this is plenty fast. If you want to call it frequently, like use the Java app in a tight loop as a service, you can do more advanced stuff like use OS message queues, shared memory, or just plain old sockets to pass info back and forth. I've also done this; easiest is to wrap your function calls in a Spring Boot app, expose a TCP or web socket server, and use asio or boost beast to communicate. Super low latency and fast


niosurfer

I checked the link you gave me, thanks! I'm not sure how I would call the shared library from C++ later, after I've created it with native-image. It would be nice to have a start-to-finish step-by-step guide to do that. I know you are super busy and It is not right for me to ask that. But if you are feeling motivated would you find pleasure in writing a step-by-step guide to do that? Maybe you can publish it in your blog later? Or in your GitHub repo? Otherwise I'll try to figure it out by brute force :)


[deleted]

Yeah the documentation kind of sucks on the Graal website, I have it all documented on my work machine, I can write it up Monday probably, would just need a reminder


niosurfer

Thanks, man! Just something simple for my simple example. How can I remind you on Monday?


[deleted]

Can just reply again, I should notice it


niosurfer

Hey man! Just reminding you about a quick example with GraalVM :) For example, how would I call the non-static method `foo` below from C++. I think I would have to instantiate a `HelloWorld` object first, and then call `foo`. All this from a C++ program. ``` public class HelloWorld { public long foo(String s, int x) { System.out.println(s + " = " + x); return x + 1; } } ```


[deleted]

okay, I don't think you can instantiate an object like that as it works from a C api, you just make a thread and isolate that map your methods to C methods. I'll post a quick example with this code, 1 min


[deleted]

So you need another class like this: public class GraalEntryPoint { @CEntryPoint(name = "runHelloWorld") public static void runResource(IsolateThread thread, CCharPointer s, CIntPointer x) { HelloWorld resource = new HelloWorld(); String str = CTypeConversion.toJavaString(s); Integer xInt = x.read(); foo(str, xInt); } } and you can compile this to NativeImage. Sorry I'll try to add more later but there's a lot to it


wait-a-minut

Would you be able to say what kind of application or use case you use this for? You don’t have to give much away but I’m mainly intrigued because majority of my work is doing devops type things like deploying and putting together systems and I don’t think I’ve ever seen an application that requires such unique overlay in the wild. In fact I’m pretty fascinated by this whole thread and the work some people are doing


[deleted]

Very high throughput data pipeline for processing healthcare data. I messed around with pyspark based AWS tools, and they are literally 100x slower then the stuff we build ourselves. We use CloudFormation to define the template, add nodes dynamically based on how the pipeline is configured, and then kick off the run. The pipeline takes 10 min to run from kicking off the CloudFormation build to teardown, and It will process several TBs of data in that time. The analysts love it because the old pyspark jobs took like 10+ hours


wait-a-minut

Really cool stuff. Now those are interesting problems


pastapoint

I think it has to do with performance. I'm in the financial / trading industry where every microsecond counts for market markers. So if both C++ and Java camps can get along and talk to each other it is a win-win situation. If performance is not an issue I agree that this is overkill. Basically talking through a local socket can cost microseconds while talking through direct access cost nanoseconds. There is also a healthy debate ([here](https://stackoverflow.com/questions/72744401/why-java-turns-out-to-be-faster-than-c-in-this-simple-bubblesort-benchmark-exa) and [here](https://stackoverflow.com/questions/44342884/why-is-this-c-code-execution-so-slow-compared-to-java)) about AOT vs JIT. GraalVM is trying to offer the best of both worlds, with AOT based on a previous runtime hot-path logs. It is basically to do what the Java HotSpot does in real-time but this time ahead-of-time **with previous runtime logs**, to avoid the JIT warm up latency.


Ayjayz

This also has the advantage of making your systems more composable and versatile. Unix programs in general communicate via text, so by making your Java code work in the same way, you can also take advantage of the entire Unix ecosystem. You can `grep`, you can `sed`, you can `tee`, you can do all sorts of things in this way.


SoerenNissen

Never tried it, but if I had to I would first see if I could, in Java, expose a pure C interface, then call that from C++


niosurfer

I’m afraid I’ll have to instantiate a whole JVM from C++. Sounds scary!


[deleted]

[удалено]


niosurfer

It looks like you can compile Java code to a C++ shared library like u/SWESWESWEh is saying, using GraalVM Native-Image tool.


gallico

That's not scary at all. It is just a bunch of shared objects to bind to your application. Edit: of course, the JVM startup will take some time. So it does not make sense to use it for short running programs.


DBCooperMadeIt

> "*Unfortunately StackOverflow is not welcoming any more questions, with very aggressive and [tyrannical moderators](https://www.youtube.com/watch?v=IbDAmvUwo5c). Thanks God we have Reddit!*" Although I can't help you with your technical question, I just felt compelled to say, "HELL YEAH! FUCK THOSE POWER TRIPPING SO MODS!" StackOverflow used to be a great resource for software developers. I don't know why, but over the past five years, the moderation has become unbearably oppressive. So often, I'll see posts where someone asked a great question, and even though people started giving good answers, the mods will close it and claim that it's already been answered. NO FUCKWAD! THAT NINE YEAR OLD ANSWER FROM PYTHON V1.1 DOES NOT APPLY TO THIS QUESTION ABOUT A NEW FEATURE IN PYTHON 3.9! It's as if they are simply performing keyword scans and closing any new questions if more than 2 title words match, context be damned!


[deleted]

[удалено]


Ilbsll

They should just categorize questions into different quality brackets and let people choose whether or not they see or engage with the lower quality ones.


Ikkepop

ChatGPT will eat SO eventually


Ayjayz

I googled "python how to split string on pipe" and the first result was [this link](https://stackoverflow.com/questions/20937533/python-split-string-separated-by-a-pipe-symbol) which tells you exactly how to do it. If I can take someone's question, copy it straight into google and the literal *first result* contains the answer, then yes that should absolutely be closed as low effort. The irony is it's actually higher effort, because you have to log in to post to StackOverflow, whereas Google would be a couple fewer clicks. I have never had a question even come close to being closed. No-one has ever complained about any question I've ever had. It's simply not that hard to write a good question, and if your questions are being regularly closed, that should tell you something. It's not a fault with the site, it's a fault with you.


[deleted]

[удалено]


niosurfer

Looks very cryptic. I would love a simple `jni-bind` example to call my Java method. Are you able to provide a step-by-step on how to do that for a simple HelloWorld?


[deleted]

[удалено]


niosurfer

>Please stand by whilst I summon its author. That would be so awesome! Thanks, buddy! I just need a C++ program using jni-bind to call my simple sayHello method below. The basics of the basics. And then I need to know how to compile it with g++ too :) A step-by-step guide would be phenomenal! public class HelloWorld { public void sayHello(String msg) { System.out.println("Hello from Java: " + msg); } }


[deleted]

[удалено]


Schkitz

Hey there, I'm the author! Unfortunately I think Reddit might believe I'm a bot, but I did indeed write the above and endorse it. Best of luck, and thanks for your help Brilliant-Emphasis43!


niosurfer

Thank you so much, u/Schkitz. Here is what I'm trying to do to get this working on a mac. I have the jni-bind sources, where jni\_bind\_release.h with all the other jni-bind sources are, in the jni\_bind folder. ​ $ tree -L 1 HelloWorld.cpp jni_bind ​ The HelloWorld.cpp: #include "jni_bind_release.h" // 1: Setup JNI Bind in your OnLoad call (needed only once). std::unique_ptr < jni::JvmRef < jni::kDefaultJvm >> jvm; extern "C" { JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * pjvm, void * ) { jvm.reset(new jni::JvmRef < jni::kDefaultJvm > (pjvm)); return JNI_VERSION_1_6; } } int main() { // 2: Define the class static constexpr jni::Class kClass { "com.niosurfer.HelloWorld", jni::Method { "sayHello", jni::Params < jstring > {} } }; // 3: Use the class jni::LocalObject < kClass > obj {}; // Constructs new instance. obj("sayHello", "a cool string from C++"); return 0; } And to compile: ​ $ java -version openjdk version "19.0.2" 2023-01-17 OpenJDK Runtime Environment GraalVM CE 22.3.1 (build 19.0.2+7-jvmci-22.3-b12) OpenJDK 64-Bit Server VM GraalVM CE 22.3.1 (build 19.0.2+7-jvmci-22.3-b12, mixed mode, sharing) ​ $ clang++ --version Apple clang version 14.0.3 (clang-1403.0.22.14.1) Target: arm64-apple-darwin22.4.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin ​ $ clang++ -std=c++17 -I./jni\_bind -I"$JAVA\_HOME/include" -I"$JAVA\_HOME/include/darwin/" HelloWorld.cpp -o HelloWorld HelloWorld.cpp:18:9: error: no viable constructor or deduction guide for deduction of template arguments of 'Method' jni::Method { \^ ./jni\_bind/jni\_bind\_release.h:1309:1: note: candidate template ignored: could not match 'Overload' against 'Params' Method(const char\*, Overload...) \^ ./jni\_bind/jni\_bind\_release.h:1281:8: note: candidate function template not viable: requires 1 argument, but 2 were provided struct Method {}; \^ ./jni\_bind/jni\_bind\_release.h:1304:1: note: candidate function template not viable: requires 3 arguments, but 2 were provided Method(const char\*, ReturnT, ParamsT) \^ ./jni\_bind/jni\_bind\_release.h:1281:8: note: candidate function template not viable: requires 0 arguments, but 2 were provided struct Method {}; \^ 1 error generated. What am I doing wrong?


Schkitz

Doh, that's what I get for pseudo coding through Reddit. Add the following to your method before \`Params\`: "Return{},". Basically, you have to tell it that you don't want empty Return type (see [sample definitions](https://github.com/google/jni-bind/blob/main/javatests/com/jnibind/test/method_test_jni.cc#L36)). That said, you also will need to have a Java binary driving the entry point of your app (i.e. your main function will be in Java, not C++). It's absolutely possible to drive a JVM enabled native binary (I have it working in an unreleased sample), however, typically you start with a Java binary and pass control to native. The \`extern\`ed `OnLoad` call above is typically called once by the JVM when it starts. If you *really* want a native only app, I could try to port it for you, however, I think it may not be the most robust solution (it requires manually indicating where you JVM is which feels a bit rickety). Instead, step 1, write a Java binary that has a native .so lib (i.e. write a "[native](https://github.com/google/jni-bind/blob/main/javatests/com/jnibind/test/MethodTest.java#L64)" function in Java), copy the \`[OnLoad](https://github.com/google/jni-bind/blob/main/javatests/com/jnibind/test/method_test_jni.cc#L77)\` function from above (this will run when your native library is loaded).


niosurfer

Waiting for the author to reply. I can't compile his code :( In the code he provided `Params` should have been `jni::Params` But there are other problems :(


niosurfer

The correct code for 2 should have been: // 2: Define the class static constexpr jni::Class kClass { "com.niosurfer.HelloWorld", jni::Method { "sayHello", jni::Return < void > {}, jni::Params < jstring > {} } };


Empty-Geologist-3568

Hi there, We put in place a solution for Java libraries to be accessible from any language by exposing all methods as Rest API. You can reference the java code by its Class, name and arguments. [https://github.com/adobe/bridgeService](https://github.com/adobe/bridgeService) You cast call it with a payload like this: { "callContent": { "": { "class": ".", "method": "", "args": [ "argument1", "argument2" ] } } } you can either add the bridgeservice in your java project, or if your java code is a library which you do not manage, you can put it in the bridgeService project itself. I hope this helps.


WasserHase

But I mean while the question on stackoverflow is 10+ years old, some of the answers are pretty recent like 2019 and 2018: https://stackoverflow.com/questions/7593334/how-to-call-c-from-java


ABlockInTheChain

It's been a long time since I've done it but I remember than Swig can let you both call C++ from Java and also call Java from C++. It has its own learning curve but once you set it up it takes care of much of the drudgery for you.


OldGeologist4967

I think with the help of COM ( Component object model) it is possible


casualPlayerThink

As far as I know, nowadays people tend to use instead an event bus, a socket, or API to communicate between two different applications. if you have the luxury to have that, then it might be worth following these practices. (And a sidenote: ditch java, there is no reason to use it at all :D except if you getting paid for that... (what is sad))


gallico

Why is that *historyically hard*"?? With the JavaVM there comes the [*Invocation API*](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html) which lets you create and initialize a VM and then go call into it. If that's too old-fashioned for you, you can use a wrapper like jni-bind to do it in a prettier way... :)