通过JNI加载Java VM时触发访问冲突问题求助
Java VM加载访问冲突问题排查与解决
我在加载Java虚拟机时遇到问题:调用LoadVM方法时程序触发访问冲突,但该程序在其他计算机上可正常运行。相关代码如下:
uses jni; var Options: array [0..1] of JavaVMOption; VM_args: JavaVMInitArgs; ErrCode: Integer; AJavaVM: TJavaVM; AJavaEnvMain: TJNIEnv; JrePath, ProgramPath, LibPath, File1, File2: string; begin ProgramPath := 'd:\testjava\exe\'; JrePath := ProgramPath + 'JRE\bin\client\'; LibPath := ProgramPath + 'JRE\lib\ext\'; File1 := LibPath + 'file1.jar'; File2 := LibPath + 'file2.jar'; AJavaVM := TJavaVM.Create(JNI_VERSION_1_8, JrePath + 'jvm.dll'); FillChar(Options, SizeOf(Options), #0); Options[0].optionString := PAnsiChar(AnsiString('-D java.class.path=' + File1 + ';' + File2)); VM_args.version := JNI_VERSION_1_8; VM_args.Options := @Options; VM_args.nOptions := 1; ErrCode := AJavaVM.LoadVM(VM_args); //access violation if ErrCode < 0 then raise Exception.CreateFmt('Initialization error JVM, błąd %d.', [ErrCode]); end;
排查与解决步骤
- 确认架构匹配:确保Delphi程序的编译架构(32位/64位)与目标机器上的JRE架构完全一致。32位程序必须使用32位JRE的
jvm.dll,64位程序对应64位JRE,架构不匹配是访问冲突的高频原因。 - 验证JRE路径与文件完整性:
- 检查
JrePath指向的路径是否存在jvm.dll,注意路径末尾斜杠是否正确,避免拼接后路径错误。 - 对比正常运行的机器,检查目标机器上的JRE目录是否完整,
client/server文件夹下的核心库是否未损坏。
- 检查
- 修复字符串生命周期问题:
代码中临时AnsiString转换为指针后可能被释放,导致optionString指向无效内存。修改为以下方式:
同时注意JNI参数格式要求var ClassPathOpt: AnsiString; begin // ... 其他代码 ClassPathOpt := AnsiString('-Djava.class.path=' + File1 + ';' + File2); // 注意-D与参数间无空格 Options[0].optionString := PAnsiChar(ClassPathOpt); // ... 后续代码-Dkey=value,-D和参数之间不能加空格,否则会导致参数解析失败。 - 完整初始化VM_args结构体:
JavaVMInitArgs包含多个字段,仅初始化部分字段可能导致垃圾数据引发访问冲突,建议先填充整个结构体:FillChar(VM_args, SizeOf(VM_args), #0); VM_args.version := JNI_VERSION_1_8; VM_args.Options := @Options; VM_args.nOptions := 1; VM_args.ignoreUnrecognized := False; // 显式设置字段值 - 检查权限与依赖:
- 尝试以管理员身份运行程序,排查是否因权限不足导致无法读取JRE文件或写入临时目录。
- 使用
Dependency Walker工具检查jvm.dll的依赖库是否全部存在,目标机器可能缺失必要的系统库或JRE依赖库。
内容的提问来源于stack exchange,提问作者Jacek U
相关产品推荐
相关产品推荐

