首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在启动JVM之前确定JNI/JVM版本

在启动JVM之前确定JNI/JVM版本
EN

Stack Overflow用户
提问于 2022-06-14 08:53:26
回答 2查看 266关注 0票数 0

我有一个使用JNI嵌入JVM并支持各种Java版本的C应用程序。该应用程序运行在linux、OSX和windows上。

目前,它允许通过环境变量提供JVM args,但我希望使它更智能。

不幸的是,我需要根据Java版本不同地设置一些VM参数。

如果我有一个使用JNIEnv*GetVersion,我就可以得到这个版本了--但是当我有了一个JNIEnv*时,我已经建立了一个JVM,但为时已晚。(您不能关闭并重新启动一个新JVM。)

看起来,JNI_GetDefaultJavaVMInitArgs可以做到这一点--但是,尽管它编译的很好,但我无法从它得到一个合理的答案。例如,使用Java 9:

代码语言:javascript
复制
    JavaVMInitArgs vmArgs;
    vmArgs.version = JNI_VERSION_1_2;
    if (JNI_GetDefaultJavaVMInitArgs(&vmArgs)!=JNI_OK) {
        fprintf(stderr, "JNI_GetDefaultJavaVMInitArgs failed!\n");
    };
    fprintf(stderr, "Query with version = %x\n", JNI_VERSION_1_2);
    fprintf(stderr, "JAVA version = %x\n", vmArgs.version);

版画

代码语言:javascript
复制
Query with version = 10002
JAVA version = 10002

也就是说,它还没有更新版本。

有没有办法(以跨平台的方式)获取这些信息?我在使用JNI_GetDefaultJavaVMInitArgs时做错了什么吗?

EN

回答 2

Stack Overflow用户

发布于 2022-06-14 11:05:03

为什么不先做最简单的事情,然后在一个单独的进程中启动一个JVM来计算JVM版本:

代码语言:javascript
复制
int fds[2];
pipe(fds);
if (fork() == 0) { // child
  close(fds[0]);
  JavaVMInitArgs vm_args;
  vm_args.version = JNI_VERSION_1_2;
  vm_args.options = nullptr;
  vm_args.nOptions = 0;
  vm_args.ignoreUnrecognized = true;

  JNIEnv *env = nullptr;
  jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

  jclass cls_Runtime = env->FindClass("java/lang/Runtime");
  jmethodID mid_version = env->GetStaticMethodID("version", "()Ljava/lang/Runtime$Version;");
  jobject obj_Version = env->CallStaticObjectMethod(cls_Runtime, mid_getVersion);

  jclass cls_Version = env->GetObjectClass(obj_Version);
  jmethodID mid_toString = env->getMethodID(cls_Version, "toString", "()Ljava/lang/String;");
  jstring str_Version = (jstring) env->CallObjectMethod(obj_version, mid_toString);

  const char *version = env->GetStringUTFChars(str_Version, null);

  write(fds[1], version, env->GetStringUTFLength(str_Version));
  exit(0);
} else if (fork() > 0) { // parent
  close(fds[1]);
  char version[100];
  int size = read(fds[0], version, 100);
  close(fds[0]);
  version[size] = '\0'; 
  // continue initialization
} else { // error }

当然,与调用toString不同,您只需抓取feature()即可。

票数 3
EN

Stack Overflow用户

发布于 2022-06-23 02:55:13

您必须区分JNI和JVM。每个JVM版本都支持一组JNI,这取决于其版本(最新列表请参见https://docs.oracle.com/en/java/javase/18/docs/specs/jni/functions.html#version-information )。当您请求激活JVM时,您必须设置您的应用程序编写的JNI的最小版本;C链接是增量式的,例如,GetModule可以从版本9中获得。如果您使用CreateJavaVM的最高版本调用JNI而不是JVM支持的版本,则API返回JNI_EVERSION。

如果应用程序的参数依赖于JVM版本,则JNI版本是无用的:最新的JNI版本是10,从JRE 10到JRE 18是相同的。

为了能够调用JNI,您必须加载JVM主库。当加载JVM库时,您将决定使用哪个版本的JVM,从而决定JNI版本。一个系统可以安装多个JVM,一个是默认的,另一个是可以使用jvm.dll、libjvm.so等路径访问的。一般来说,JVM的版本是在路径中编写的,它取决于规范、构建、供应商、平台等许多方面。这是apt的输出:

代码语言:javascript
复制
sudo apt install openjdk-11-jre-headless  # version 11.0.10+9-0ubuntu1~20.04, or
sudo apt install default-jre              # version 2:1.11-72
sudo apt install openjdk-8-jre-headless   # version 8u282-b08-0ubuntu1~20.04
sudo apt install openjdk-13-jre-headless  # version 13.0.4+8-1~20.04
sudo apt install openjdk-14-jre-headless  # version 14.0.2+12-1~20.04

您可以解析JVM库的路径,试图标识JRE规范(8、11、13、.)然后,您可以使用应用程序为该版本所需的参数调用CreateJavaVM

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72614118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档