Java学习:J2V8与Javet的对比

V8是谷歌开发的开源JavaScript引擎。它被赞誉为快速、应用最新的ES等各种优点。V8是用C++编写的,但如果要从Java使用V8,就需要使用包装器。

    一番有名なのは、J2V8です。だが更新が止まっているみたいで、windows向けのバージョンは2016年の4.6.0まで、async/awaitはサポートしていないです。詳細は以下のリンクから確認してください。

 

    2番めは、javetです。V8の2023年10月のv11.8.172.15、node.jsも9月v20.8.0を利用されています。認知度がJ2V8よりちょっと低いかもしれません。後発ですからJ2V8より使い勝手がいいです。

 

<dependency>
    <groupId>com.caoccao.javet</groupId>
    <artifactId>javet</artifactId>
    <version>3.0.0</version>
</dependency>

J2V8和Javet在使用上的差异。

测试a.js

global.myVar="aaaaaaaaaa";

testb.js 的中文释义可以是 “测试b.js”。

global.myVar="bbbbbbbbbb";

测试J2V8.java

import java.io.File;
import java.io.IOException;

import com.caoccao.javet.exceptions.JavetException;
import com.eclipsesource.v8.NodeJS;

public class TestJ2V8 {
	public static void main(String[] args) throws IOException,  InterruptedException, JavetException {
		final NodeJS nodeJS = NodeJS.createNodeJS();
		File testa=new File("testa.js");
		nodeJS.exec(testa);
		File testb=new File("testb.js");
		nodeJS.exec(testb);
		while (nodeJS.isRunning()) {//実行完了まで待つ
			nodeJS.handleMessage();
		}
		System.out.println(nodeJS.getRuntime().getString("myVar"));
		nodeJS.release();
	}
}

TestJavet.java的测试

import java.io.File;
import java.io.IOException;

import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interop.V8Host;
import com.caoccao.javet.interop.V8Runtime;
import com.caoccao.javet.interop.executors.IV8Executor;

public class TestJavet {
	public static void main(String[] args) throws IOException,  InterruptedException, JavetException {
		try (V8Runtime v8Runtime = V8Host.getNodeInstance().createV8Runtime()) {
			IV8Executor iV8Executor=v8Runtime.getExecutor(new File("testa.js"));
			iV8Executor.executeVoid();
			v8Runtime.await();//実行完了まで待つ
			iV8Executor=v8Runtime.getExecutor(new File("testb.js"));
			iV8Executor.executeVoid();
			v8Runtime.await();//実行完了まで待つ
			System.out.println(v8Runtime.getGlobalObject().getString("myVar"));
		}
	}
}

javet的v8Runtime.await()调用与j2v8中的while (nodeJS.isRunning())具有类似的功能,但v8Runtime.await()可以被调用多次。而while (nodeJS.isRunning())只能被调用一次,执行后V8将处于停止状态,无法再执行更多的js文件。j2v8没有类似于v8Runtime.await()的功能,因为它是在2016年之前的版本。

并且,由于J2V8无法作为EFW的loadWithGlobalPool函数的内置JavaScript引擎使用,因此无法从池中获取并返回引擎的使用。这是因为引擎的使用不仅限于一次,而是会多次间歇性地发生。

另外,Javet具有Primitive Converter和Object Converter的机制,可以自动进行Java和JavaScript之间的转换。J2v8中存在类似的Primitive Converter机制,但没有等效的Object Converter机制。当从Java将Byte[]传递到引擎时,我们需要手动将其转换为V8Array并传递给引擎。这将导致额外的学习和工作量。

 

J2V8和Javet在多线程方面的区别

根据结论来看,J2V8不允许多线程。Javet允许多线程。

    まずJ2V8とJavetのラインタイムをstatic変数に定義します。
package test;
import com.eclipsesource.v8.V8;
public class TestJ2V82 {
	public static V8 runtime = V8.createV8Runtime();
	static {
		runtime = V8.createV8Runtime();
		runtime.executeVoidScript("var c=0;function hello(){c++;return c;};");
	}
}
package test;
import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interop.V8Host;
import com.caoccao.javet.interop.V8Runtime;
public class TestJavet2 {
	public static V8Runtime v8Runtime;
	static {
		try {
			v8Runtime = V8Host.getNodeInstance().createV8Runtime();
			v8Runtime.getExecutor("var c=0;function hello(){c++;return c;};").executeVoid();
		} catch (JavetException e) {
			e.printStackTrace();
		}
	}
}

我将创建一个使用各自的静态变量的JSP文件test_subJ2V8.jsp。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="test.TestJ2V82"%>
<%@ page import="com.eclipsesource.v8.V8"%>

<%
	V8 runtime =TestJ2V82.runtime;
	out.println(runtime.executeStringScript("''+hello();"));
	out.println("<br>");
	out.println(runtime.executeStringScript("''+hello();"));
%>

测试_subJavet.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="test.TestJavet2"%>
<%@ page import="java.io.File"%>
<%@ page import="java.io.IOException"%>
<%@ page import="com.caoccao.javet.exceptions.JavetException"%>
<%@ page import="com.caoccao.javet.interop.V8Host"%>
<%@ page import="com.caoccao.javet.interop.V8Runtime"%>
<%@ page import="com.caoccao.javet.interop.executors.IV8Executor"%>

<%
	V8Runtime v8Runtime=TestJavet2.v8Runtime;
	out.println(v8Runtime.getExecutor("hello()").executeInteger());
	out.println("<br>");
	out.println(v8Runtime.getExecutor("hello()").executeInteger());
%>

我将创建一个测试页面,以同时调用10次上述的JSP页面。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="efw" uri="efw" %> 
<!DOCTYPE HTML>
<HTML>
<HEAD>
	<META HTTP-EQUIV="CONTENT-TYPE"CONTENT="TEXT/HTML;CHARSET=UTF-8">       
	<TITLE>efw Output Test</TITLE>
	<!-- Efwクライアントの取り込み-->
	<efw:Client lang="jp"/>
	<script>
	function testJavetM(flg){
		$("#pdf0")[0].src="";
		$("#pdf1")[0].src="";
		$("#pdf2")[0].src="";
		$("#pdf3")[0].src="";
		$("#pdf4")[0].src="";
		$("#pdf5")[0].src="";
		$("#pdf6")[0].src="";
		$("#pdf7")[0].src="";
		$("#pdf8")[0].src="";
		$("#pdf9")[0].src="";
		setTimeout(function(){
			$("#pdf0")[0].src="test_sub"+flg+".jsp";
			$("#pdf1")[0].src="test_sub"+flg+".jsp";
			$("#pdf2")[0].src="test_sub"+flg+".jsp";
			$("#pdf3")[0].src="test_sub"+flg+".jsp";
			$("#pdf4")[0].src="test_sub"+flg+".jsp";
			$("#pdf5")[0].src="test_sub"+flg+".jsp";
			$("#pdf6")[0].src="test_sub"+flg+".jsp";
			$("#pdf7")[0].src="test_sub"+flg+".jsp";
			$("#pdf8")[0].src="test_sub"+flg+".jsp";
			$("#pdf9")[0].src="test_sub"+flg+".jsp";
		},100);
	}
	</script>
</HEAD>
<BODY>
<button onclick="testJavetM('Javet');">マルチJavet</button>
<button onclick="testJavetM('J2V8');">マルチJ2V8</button>
<br>
<iframe id="pdf0" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf1" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf2" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf3" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf4" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf5" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf6" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf7" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf8" src="" style="width:400px;height:300px"></iframe>
<iframe id="pdf9" src="" style="width:400px;height:300px"></iframe>
</BODY>
</HTML>
image.png
image.png
    マルチスレッドについて、Graaljsもだめです。QuickJSもだめです。逆にむかしのNashornとRhinoは可能です。ようやくES2015以上サポート且つマルチ可能のエンジンを見つかりました。

結果

Javet很好,我们来试试使用吧。

广告
将在 10 秒后关闭
bannerAds