当前位置: 首页 > 工具软件 > J2V8 > 使用案例 >

J2V8 error: Invalid V8 thread access

单于钊
2023-12-01

今天使用j2v8在java中执行JavaScript代码时,遇到了一个错误:

Exception in thread "Thread-2" java.lang.Error: Invalid V8 thread access
	at com.eclipsesource.v8.V8Locker.checkThread(V8Locker.java:56)
	at com.eclipsesource.v8.V8.checkThread(V8.java:676)

一个简单的报错示例:

    @Test
    public void test() throws InterruptedException {
        AtomicReference<V8> v8 = new AtomicReference<>();
        new Thread(() -> {
            v8.set(V8.createV8Runtime());
        }).start();
        Thread.sleep(5000);
        v8.get().executeScript("const i = 0;"); // 此处报错
        v8.get().release();
    }

跟踪checkThread方法:

    public void checkThread() {
        if (this.thread != Thread.currentThread()) {
            throw new Error("Invalid V8 thread access");
        }
    }

发现在比对 this.threadThread.currentThread 是否一致,Thread.currentThread 是当前正在执行的线程,而 this.thread 则是V8Runtime创建时的线程,当两个线程不一致时就会抛出这个错误,而 this.thread 存在于V8Locker,v8locker提供两个跟 this.thread 相关的方法,release和acquire:

    public synchronized void acquire() {
        if (this.thread != null && this.thread != Thread.currentThread()) {
            throw new Error("Invalid V8 thread access");
        } else {
            this.thread = Thread.currentThread();
        }
    }

    public synchronized void release() {
        this.checkThread();
        this.thread = null;
    }

所以可以得出解决方案,在创建v8Runtime的线程中释放v8Locker中锁定的线程,然后在使用v8的线程中将当前线程绑定到v8Locker中。

上边报错示例的解决方案:

    @Test
    public void test() throws InterruptedException {
        AtomicReference<V8> v8 = new AtomicReference<>();
        new Thread(() -> {
            V8 v=V8.createV8Runtime();
            v.getLocker().release(); // 在创建runtime的线程中release
            v8.set(v);
        }).start();
        Thread.sleep(5000);
        v8.get().getLocker().acquire();// 在使用runtime的线程中acquire
        v8.get().executeScript("const i = 0;");
        v8.get().release();
    }

注:release和acquire二者缺一不可。

 类似资料:

相关阅读

相关文章

相关问答