我目前正在进行一个Java/C混合项目. 因为我喜欢尽可能地减少运行时障碍,所以我倾向于将资源(图片)集成到我的二进制文件中,从而消除了当用户移动我的二进制文件时可能发生的"Picture Not Found"之类的错误. 我知道我可以将Java文件包含到我的C可执行文件中(例如,通过C23#Emed或xxd).通常,在现代机器上,相当于几MB的二进制代码不再是问题. 然后,我可以通过(程序开头的一个简单的Foreach循环)在我的C程序中加载类:

jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize bufLen);

我的问题是:我如何才能对整个jar文件做到这一点?我想在我的二进制文件中包含selenium API?它是否足够解压缩每个jar文件,将其包含在二进制文件中,并定义它们? 有没有什么障碍是我可能忽略的?

编辑:我的切入点是在C端.事实上,整个应用程序不包含任何Java代码,它只是通过JNI使用了Selenium的一些API.

推荐答案

作为完全不同的方法,为什么不滥用JAR底层的ZIP文件格式呢?ZIP文件将其元数据存储在文件的末尾,这意味着您可以简单地将ZIP文件附加到二进制文件中,运行嵌入式JVM,并将二进制文件添加到自己的类路径中.添加全部的selenium,然后只是一个重新包装到一个单一的uberjar的问题.

作为一个简单的例子,以Main.java为例:

class Main {
    public static void main(String[] args) {
        System.out.println("Hello from java");
    }
}

和jni.cpp:

#include <jni.h>
#include <string>

int main(int argc, char **argv) {
    JavaVM *jvm;       /* denotes a Java VM */
    JNIEnv *env;       /* pointer to native method interface */
    JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
    JavaVMOption* options = new JavaVMOption[1];
    std::string option = "-Djava.class.path=";
    option += argv[0];
    options[0].optionString = const_cast<char *>(option.c_str());
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = options;
    vm_args.ignoreUnrecognized = false;
    /* load and initialize a Java VM, return a JNI interface
     * pointer in env */
    JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
    delete[] options;
    /* invoke the Main.test method using the JNI */
    jclass cls = env->FindClass("Main");
    jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(cls, mid);
    /* We are done. */
    jvm->DestroyJavaVM();
}

然后,您可以执行以下操作:

$ make jni
$ javac Main.java
$ jar cf code.jar Main.java
$ cat jni code.jar > jni-combined
$ ./jni-combined
Hello from java

Java相关问答推荐

我们如何直接使用kerminldap服务票证来通过ldap进行身份验证并形成LDAP上下文

为什么BasicComboBoxRenderer在文本不存在或文本为空的情况下设置两次文本?

现场观看Android Studio中的变化

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

对于几乎不涉及逻辑的请求,您是否应该使用命令模式?

在Java中,在单个逻辑行中连接列表和单个元素的正确方法是什么?

试着做一个2x2的魔方求解算法,我如何找到解路径(DFS)?

为什么使用JDK21获取锁定锁比使用JDK11慢

Bean定义不是从Spring ApplationConext.xml文件加载的

由于 list 中的权限错误,Android未生成

带有Health Check的Spring Boot BuildPack打破了本机映像构建过程

如何在JavaFX循环中完美地制作一个AudioClip/MediaPlayer?

如何在太阳系模拟器中添加月球?

Domino中不同的java.Protocol.handler.pkgs设置在XPages Java中导致错误

我的代码是线程安全的吗?[Java、CAS、转账]

如何使用Java对随机生成的字母数字优惠券代码进行过期设置

通过/失败的参数化junit测试方法执行数

我们可以在方法中声明接口吗?

如何修复Spring Boot应用程序中的RestDocumentationGenerationException:java.io.FileNotFoundException:/curl-request.adoc(只读文件系统)?

Hibernate 命名策略导致 Java Spring Boot 应用程序中出现未知列错误