2

I am having a rather interesting scenario here. Let's say I have a piece of C code stored in a Java String. I need to run this code inside my Java program it self.

Case 1

class Main{
      public static void main(String[] args) {
           String cCode  = "printf(\"Hello World\n\");"
            // I need to run the cCode here.
            // We are allowed to  call a method with params.
       }
}

What I think I should do is.

  1. Create a native field in the Main
  2. write the sCode to a file
  3. Exceulte shell commands from Java to compile the c code.
  4. invoke the native method from java

Case 2

I am thinking of doing the above procedure because I know how to do this with JNI if the source code is pre-defined.

 class Main{

      static {
        System.loadLibrary("Main"); // Load native library at runtime
      }

      private native void sayHello();

      public static void main(String[] args) {
        new Main().sayHello();
      }

    }

In the case of pre-written C code. What we do is.

  1. Compile the java class with javac Main.java
  2. Generate the header for C lib. javah -jni Main
  3. Complete the Main.c by writing the C code
  4. Compile the C code with gcc -share -I/path/to/jni -I/path/to/jni_md -o Main.so
  5. Run Main. java Main

Can anyone tell me whether I am taking the correct path (in Case 1) or not? or is there is a better way to do it?

** Note: The key point here is, I am allowed to compile the java code only once. (At the beginning).**

EDIT: After checking the comments and answer from @Dúthomhas I think I should explain one more thing. The reason why I am doing this for a machine learning project. It has been decided that the numeric computation part has a bottleneck and using C as the above-mentioned method is worth the risk of trying it. So security is off the book right now. We just need to do this as an experiment.

1
  • What problem are you trying to solve with this? Commented Dec 16, 2017 at 12:35

2 Answers 2

3

Non-answer answer: Don’t do that.

What you are asking to do is a pretty bad idea for several reasons, the two major ones are:

  • It potentially opens (serious) security holes
  • Cost to implement likely outweighs the benefit

Asking to embed an entirely different language means adding and linking a library and a lot of code to synchronize the library, plus code to perform static analysis and sandbox the code. In other words, you are asking to implement an entire language on top of what you already have.

It could be argued that C is the base system anyway, upon which the JVM may even be implemented (usually is), but that is not the point. The issue is not the C library, it is the C compiler/interpreter, which is a fairly complex code base as far as simple interpreted programming languages go.

Suggestion: Use Java

The ToolProvider class is specifically designed to provide you with dynamic compilation of Java code. Take a look through it.

Make sure to use the SecurityManager class to properly sandbox the code. (And, if possible, run it in a separate, restricted JVM.)

Suggestion: Use JavaScript/ECMAScript

The ScriptEngine classes are designed exactly for this. Again, Google around for examples. And, again, don’t forget security.

Suggestion: Use an existing library

But I really want/must use C

Alas. It is possible to use C, but only with great difficulty. Google around “embedded c interpreter” for small C interpreters that you may be able to integrate into your source. (Good luck, though!)

Sign up to request clarification or add additional context in comments.

1 Comment

For a non-answer, this answer contains a very good insight on why the above should not be done. Upvote for that. I cannot accept the answer as I have not received an answer to the original question. Well, I don't want to embed an entire a language. I just want to pass an array from Java to C and receive an array. And my program is supposed to work for one dynamic C function (in a Java string).
1

Let me clarify your two Cases.

Case 1 refers to running a C program out of process. This is not what most people consider "invoke the native method from java". You cannot create a native field in Main. Actually, Java does not have native fields, only native methods. But in Case 1, you don't use native methods, either. You can compile and run any program, written in C or any other language (provided a compiler is available in the runtime environment). To do so, you use shell commands (Runtime.exec()) both to compile the program and to run it. Parameters for the C program can be passed 'on the command line' as specified in Runtime.exec(). It can communicate with your Java process with any IPC of your choice. Typically, we simply use a pipe to read the stdout of the child process.

Case 2 runs the native code in-process, using JNI (Java Native Interface). The flow that you describe here is correct, but you can modify it to use a shared library that is built at runtime. First of all, remove the native method and also loadLibrary() to a separate class. Make sure that the classloader loads this class only after your Main class runs the gcc -o libMain.so command (using the same Runtime.exec() as in Case 1). This way, the static constructor will load the freshly built library.

In both Cases you don't need to recompile your Java. You don't need to run javah to build libMain.so - this is a convenience step only, to guarantee that the C headers are in sync with the Java class. But in your situation, the Java class does not change - therefore the native method signature does not change, too.

Note that Case 1 is easier, especially if you must run different compiled C 'strings', but Case 2 may deliver better performance, if you must call the native method many times.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.