运行存储在Java String中的一段C代码

问题描述 投票:2回答:2

我在这里有一个相当有趣的场景。假设我有一段存储在Java String中的C代码。我需要在我自己的Java程序中运行这段代码。

情况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.
       }
}

我认为我应该做的是。

  1. 在Main中创建一个本机字段
  2. 将代码写入文件
  3. 来自Java的Exceulte shell命令来编译c代码。
  4. 从java调用本机方法

案例2

我正在考虑执行上述过程,因为如果源代码是预定义的,我知道如何使用JNI执行此操作。

 class Main{

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

      private native void sayHello();

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

    }

在预先编写的C代码的情况下。我们做的是。

  1. 使用javac Main.java编译java类
  2. 生成C lib的头。 javah -jni Main
  3. 通过编写C代码完成Main.c.
  4. 使用gcc -share -I/path/to/jni -I/path/to/jni_md -o Main.so编译C代码
  5. 运行Main。 java Main

谁能告诉我我是否采取了正确的路径(在案例1中)?或者有更好的方法吗?

**注意:这里的关键点是,我只允许编译一次java代码。 (开头)。**

编辑:检查@Dúthomhas的评论和回答后,我想我应该再解释一下。我为机器学习项目做这个的原因。已经确定数值计算部分具有瓶颈并且使用C作为上述方法值得尝试它的风险。所以安全性现在已经不在了。我们只需要做一个实验。

java c java-native-interface
2个回答
1
投票

让我澄清你的两个案例。

案例1指的是在运行过程中运行C程序。这不是大多数人认为“从java调用本机方法”的内容。您无法在Main中创建本机字段。实际上,Java没有本机字段,只有本机方法。但在案例1中,您也不使用本机方法。您可以编译和运行任何用C语言或任何其他语言编写的程序(前提是运行时环境中有编译器)。为此,您使用shell命令(Runtime.exec())来编译程序并运行它。 C程序的参数可以在Runtime.exec()中指定的'命令行'上传递。它可以与您选择的任何IPC的Java进程通信。通常,我们只是使用管道来读取子进程的标准输出。

案例2使用JNI(Java Native Interface)在进程中运行本机代码。您在此处描述的流程是正确的,但您可以对其进行修改以使用在运行时构建的共享库。首先,删除本机方法,并将loadLibrary()删除到单独的类。确保只有在Main类运行gcc -o libMain.so命令(使用与Case 1中相同的Runtime.exec())后,类加载器才会加载此类。这样,静态构造函数将加载新构建的库。

在这两种情况下,您都不需要重新编译Java。您不需要运行javah来构建libMain.so - 这只是一个方便的步骤,以保证C头与Java类同步。但在您的情况下,Java类不会更改 - 因此本机方法签名也不会更改。

请注意,案例1更容易,尤其是如果必须运行不同的已编译C'字符串',但如果必须多次调用本机方法,则案例2可以提供更好的性能。


3
投票

非答案答案:不要这样做。

由于以下几个原因,你要求做的是一个非常糟糕的主意,两个主要原因是:

  • 它可能会打开(严重)安全漏洞
  • 实施成本可能超过收益

要求嵌入完全不同的语言意味着添加和链接库和大量代码以同步库,以及执行静态分析和沙箱代码的代码。换句话说,您要求在已有的语言之上实现整个语言。

可以说C无论如何都是基本系统,甚至可以实现JVM(通常是),但这不是重点。问题不在于C库,它是C编译器/解释器,就简单的解释编程语言而言,它是一个相当复杂的代码库。

建议:使用Java

ToolProvider类专门为您提供Java代码的动态编译。看看它。

确保使用SecurityManager类正确地沙箱代码。 (并且,如果可能的话,在一个单独的受限制的JVM中运行它。)

建议:使用JavaScript / ECMAScript

ScriptEngine课程正是为此而设计的。再次,谷歌周围的例子。而且,再次,不要忘记安全。

建议:使用现有库

但我真的想/必须使用C.

唉。可以使用C,但只是非常困难。 Google围绕“嵌入式c解释器”提供小C解释器,您可以将其集成到您的源中。 (祝你好运!)

© www.soinside.com 2019 - 2024. All rights reserved.