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

Java调用Native回调引发LinkedList并发异常问题排查

问题原因分析与解决方案

你的代码出现NullPointerException和ConcurrentModificationException,核心原因是非线程安全的LinkedList在并发场景下被修改与遍历,具体拆解如下:

可能的触发原因

  • 回调与遍历的线程并发
    虽然你提到Native代码未自行创建线程,但javacpp在处理JNI回调时,可能存在回调在其他线程触发的情况——比如Native依赖了系统底层的异步机制(如IO事件线程、信号处理线程),或是javacpp内部复用了线程池,导致handler.call()的add操作和scan()中的forEach遍历在不同线程同时执行。LinkedList本身没有任何线程安全保护,并发的修改与遍历会直接破坏其内部节点指针结构(比如迭代器的next指针变为null),或是触发快速失败机制抛出ConcurrentModificationException。

  • 回调执行时机超出预期
    即使callToNativeLib()是同步调用,也可能存在Native在返回后仍触发回调的情况——比如Native内部使用了本地异步任务队列,在callToNativeLib()返回后才执行回调逻辑,此时forEach已经开始遍历,导致并发修改。

解决方案

针对这些问题,可以采用以下几种修复方式:

  1. 替换为线程安全集合
    把LinkedList<Long>换成CopyOnWriteArrayList<Long>,它会在每次修改时复制底层数组,遍历操作基于快照进行,不会因并发修改抛出异常:

    private final CopyOnWriteArrayList<Long> matchedIds = new CopyOnWriteArrayList<>();
    

    或者使用Collections.synchronizedList包装LinkedList,但遍历需要手动加锁:

    private final List<Long> matchedIds = Collections.synchronizedList(new LinkedList<>());
    
    // 遍历的时候加锁
    synchronized(matchedIds) {
        matchedIds.forEach(System.out::println);
    }
    
  2. 确保回调完全完成后再遍历
    如果回调确实应该在callToNativeLib()返回前全部执行,可添加同步机制确认所有回调完成,比如用CountDownLatch:

    class Scanner {
        private final LinkedList<Long> matchedIds = new LinkedList<>();
        private CountDownLatch latch;
    
        private final Handler handler = new Handler() {
            public void call(int id) {
                matchedIds.add((long)id);
                latch.countDown();
            }
        };
    
        public void scan() throws InterruptedException {
            // 假设提前知道回调触发次数,或者从Native获取次数
            latch = new CountDownLatch(预计回调次数);
            callToNativeLib(handler);
            latch.await(); // 等待所有回调完成
            matchedIds.forEach(System.out::println);
        }
    }
    
  3. 遍历前复制集合快照
    在遍历前复制一份集合的快照,避免后续修改影响遍历过程:

    new ArrayList<>(matchedIds).forEach(System.out::println);
    

内容的提问来源于stack exchange,提问作者milan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:25:25