You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JNI新建线程通知Java线程在Eclipse正常、导出可运行Jar后失效问题咨询

问题根因分析

static final修饰的变量是类加载器级别的单例,不是JVM全局单例。你遇到的同个静态变量有两个不同ObjectID的情况,本质是你的MainClass被两个不同的类加载器分别加载了,两套静态变量互相独立,用各自的对象做锁自然无法实现等待通知逻辑。

Eclipse中运行正常是因为Eclipse默认用同一个应用类加载器加载所有项目类,不会出现重复加载的情况;导出可运行Jar后出现问题,通常是Jar打包方式、JNI类查找逻辑两个方向出了问题。

排查点清单
  • 验证类加载器是否一致
    分别在ServerConnectionWatchDog.run()和onJNICallbackEvent()方法中添加日志,打印当前MainClass对应的类加载器:
    System.out.println(MainClass.class.getClassLoader());
    
    运行Jar后如果两次打印结果不一致,即可确认是类重复加载问题。
  • 检查JNI侧类查找逻辑
    你通过env->FindClass()查找MainClass的操作如果是在attach的JNICallback守护线程中执行的,会出现类加载器异常:原生线程attach到JVM后没有默认的上下文类加载器,FindClass只会从启动类加载器路径搜索类,大概率会加载到错误的MainClass实例。
    解决方法:在Java侧启动时就把onConnectEvent对象的全局引用缓存到JNI侧,后续直接用这个缓存的对象做锁操作,不要在原生线程中动态查找类和静态变量。
  • 检查可运行Jar的打包配置
    如果你导出Jar时选择了「将依赖库打包到Jar中」的选项,要检查解压后的Jar内是否存在重复的MainClass字节码文件,或者依赖包中是否存在同包同名的类。
  • 快速验证锁对象冲突
    你可以临时把锁对象替换为全局唯一的字符串常量,字符串常量不受类加载器影响,全局共享同个实例:
    static final Object onConnectEvent = "MY_UNIQUE_LOCK_KEY_2024";
    
    如果替换后通知逻辑恢复正常,即可完全确认是类加载器导致的静态变量多实例问题。

内容的提问来源于stack exchange,提问作者Павел

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 10:06:03