首页 > 编程语言 >JS引擎(2):Java平台上JavaScript引擎—Rhino/Nashorn概述

JS引擎(2):Java平台上JavaScript引擎—Rhino/Nashorn概述

时间:2023-04-09 18:22:11浏览次数:47  
标签:Java 字节 JavaScript Nashorn Rhino 引擎 JVM

可以后端开发的 javascript引擎有

  • Chrome V8 基于C++

  • java的Rhino引擎(JDK6被植入),Java8 被替换为Nashorn

Rhino和Nashorn都是用Java实现的JavaScript引擎。它们自身都是普通的Java程序,运行在JVM上

Rhino简介

Rhino [ˈraɪnəʊ]是一种使用 Java 语言编写的 JavaScript 的开源实现,原先由Mozilla开发。

Rhino 是一种动态类型的、基于对象的脚本语言,它可以简单地访问各种 Java 类库。

当时Netscape想用纯Java来实现新版浏览器,自然需要一个Java版的JavaScript引擎实现;另外也希望能在服务器端把JavaScript当作Java应用里的脚本语言使用。于是Rhino就诞生了。

官网自带Rhino历史,跟Wikipedia上的Rhino词条基本上一样,有兴趣的话可以去看看。

Parser是从SpiderMonkey移植过来的。自然也是手写的纯递归下降式。
JavaScript对象的接口是org.mozilla.javascript.Scriptable。主要实现类是IdScriptableObject、ScriptableObject。用Object[]来存字段,挺高效的。

IdScriptableObject {
  Object[] valueArray;
  short[] attributeArray;
  // ...
}

Rhino可以通过参数从11个预设的优化基本中选择一个使用。只从JVM以上的层面看,Rhino既可以工作于纯解释模式(-1),也可以工作于纯编译模式(0-9)。这11个级别分别是

Rhino 优化级别

当优化级别为-1时,Rhino使用一个用Java写的字节码解释器来解释执行JavaScript。

此时,Rhino的工作流程简单说是:( [ ... ]表示数据实体,( ... )表示Rhino处理数据的程序)

[ JavaScript源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ast ] -> ( Rhino内部表现形式生成器 IRFactory ) -> [ Rhino内部表现形式 ScriptNode ] -> ( Rhino字节码生成器 CodeGenerator ) -> [ Rhino字节码 Icode ] -> ( Rhino解释器 Interpreter ) -> [ 运行结果 ]

这里说的Rhino字节码是Rhino内部用来表示JavaScript程序语义的一套字节码,跟JVM所支持的Java字节码没关系。      
当优化级别为0~9时,Rhino使用一个用Java写的编译器将JavaScript编译为Java字节码;生成出来的Java字节码交由JVM直接执行。至于底下的JVM是解释执行Java字节码,还是将Java字节码编译为机器码再执行,Rhino并不关心。
此时,Rhino的工作流程简单说是:

[ JavaScript源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ast ] -> ( Rhino内部表现形式生成器 IRFactory ) -> [ Rhino内部表现形式 ScriptNode ] -> ( 可选优化 Optimizer ) -> ( Java字节码生成器 Codegen ) -> [ Java Class文件(包含Java字节码) ] -> JVM加载和执行生成的字节码 -> [ 运行结果 ]

只从JVM以上的层面看,Nashorn是一种单层的纯编译型JavaScript实现。所有JavaScript代码在首次实际执行前都会被编译为Java字节码交由JVM执行。

这种以编译的方式模式执行JavaScript,跟一个Java源码编译器(例如javac)把Java源码编译为Class文件然后交由JVM执行,过程是类似的。只不过Rhino做的优化不够多而且JavaScript的语义也远比Java动态,所以此时Rhino上运行JavaScript的性能仍然无法跟Java的性能比。     

JDK6 JDK7  Rhino区别

顺带一提,Sun/Oracle JDK6 / OpenJDK6中自带的Rhino是经过裁剪的,去掉了Mozilla Rhino中的部分功能。其中一个被去掉的功能就是Rhino的编译模式。这意味着JDK6自带的Rhino只能用解释模式运行。

而Oracle JDK7 / OpenJDK7放宽了这一限制,当有SecurityManager时只能用解释模式,否则可以配置"rhino.opt.level"系统属性来设置Rhino的优化级别;默认仍然是用解释模式(优化级别默认为-1)。

Nashorn起初是Oracle内部一个实验项目,用于验证JSR 292功能的完整性、可用性、易用性。后来得到了内部的关注,决定将其产品化,作为默认的JavaScript实现替换掉从JDK6开始包含在JDK之中的Rhino。

Nashorn

Nashorn(读作Naz-horn[naːsˌɔn])是Oracle全新开发的JavaScript实现。高度兼容ECMAScript 5标准,并尽可能兼容Rhino。它使用Java语言实现,运行在JVM上,借助JDK7开始包含的JSR 292(invokedynamic)新功能达到较高的性能,同时保持代码的相对整洁

在2012年底Nashorn就已经达到可以完全通过test262测试套件的兼容性,就这点说它甚至比SpiderMonkey、V8更佳兼容于标准。

Nashorn是一个纯编译的JavaScript引擎。它没有用Java实现的JavaScript解释器,而只有把JavaScript编译为Java字节码再交由JVM执行这一种流程,跟Rhino的编译流程类似

Nashorn还在快速开发中,日新月异,所以它的工作流程在不断变化。简单来说,Nashorn的编译入口可以从Context.compile()开始看:

[ JavaScript源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ir ] -> ( 编译优化 Compiler ) -> [ 优化后的AST + Java Class文件(包含Java字节码) ] -> JVM加载和执行生成的字节码 -> [ 运行结果 ]

只从JVM以上的层面看,Nashorn是一种单层的纯编译型JavaScript实现。所有JavaScript代码在首次实际执行前都会被编译为Java字节码交由JVM执行。

(当然JVM自身可能是混合执行模式的,例如HotSpot VM与J9 VM。所以Nashorn在实际运行中可能需要一定预热才会达到最高速度)

Nashorn不但可以执行JavaScript,还可以当作库为其它工具提供一些基础服务。例如说它现在为NetBeans IDE中的JavaScript编辑器提供语法高亮支持和调试支持

从Oracle JDK 8 build 82开始,Nashorn已经作为JDK8的一部分包含在安装包中。安装后可以在JDK安装目录的jre/lib/ext/nashorn.jar找到Nashorn的实现。

直接使用Java类的实例来容纳JavaScript对象的字段,在对象内嵌入字段而不放在spill array里的好处是:

  1. 对象更加紧凑,数据离得更近,局部性更好

  2. 数组访问有边界检查,而对象字段访问则没有,后者效率更高

 

参考内容:

Rhino 和 Nashorn 到底怎么运行? - RednaxelaFX的回答 - 知乎 https://www.zhihu.com/question/27631001/answer/37407481

各JavaScript引擎的简介,及相关资料/博客收集帖 https://hllvm-group.iteye.com/group/topic/37596


转载本站文章《JS引擎(2):Java平台上JavaScript引擎—Rhino/Nashorn概述》,
请注明出处:https://www.zhoulujun.cn/html/webfront/browser/webkit/2020_0718_8520.html

标签:Java,字节,JavaScript,Nashorn,Rhino,引擎,JVM
From: https://www.cnblogs.com/zhoulujun/p/17300739.html

相关文章

  • JS引擎(0):JavaScript引擎群雄演义—起底JavaScript引擎
    JavaScript既是一个 面向过程的语言 又是一个 面向对象的语言。在JavaScript中,通过在运行时给空对象附加方法和属性来创建对象,与编译语言如C++和Java中常见的通过语法来定义类相反。对象构造后,它可以用作是创建相似对象的原型。JavaScript的动态特性包括运行时构造对......
  • 浏览器层面优化前端性能(2):Reader引擎线程与模块分析优化点
    Reader引擎线程与模块分析 首先是网页内容,加载完输入到HTML解释器,解释后构成DOM树,这期间如果遇到JavaScript代码就交给JavaScript引擎去处理,如果网页中包含CSS,就交给CSS解释器;DOM树简历的时候,渲染引擎接收来自CSS解释器的样式信息,构建一个新的你日不会吐模型,该模型由布局模......
  • Java: switch lambda-like syntax
     Theswitchexpressionhasanadditionallambda-likesyntaxanditcanbeusednotonlyasastatement,butalsoasanexpressionthatevaluatestoasinglevalue. Withthenewlambda-likesyntax,ifalabelismatched,thenonlytheexpressionorstat......
  • JavaWeb-24课-filter-2023-04-09
    Servlet类,没有乱码处理packagecom.feijian.servlet;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;public......
  • Golang与Java全方位对比总结
    本文针对Golang与Java的基础语法、结构体函数、异常处理、并发编程及垃圾回收、资源消耗等各方面的差异进行对比总结,有不准确、不到位的地方还请大家不吝赐教。一、基础语法Golang:编码风格及可见域规则严格且简单;Java:来说层次接口清晰、规范,主要表现有以下这些。1、变量......
  • leetcode56.合并区间-java
    1classSolution{2publicint[][]merge(int[][]intervals){3/*4思路:左区间排序,若intervals[i][0]>=intervals[i-1][1];则重叠5将重叠区间新建放入res数组里,没重叠则放入原数组6*/7List<int[]>......
  • javaEE进阶小结与回顾(三)
    集合概述集合是Java中存储引用数据类型的一种容器特点大小不固定,长度可以动态变化,适合做数据的增删如果集合不声明泛型,可以存入任意引用数据类型的数据(不推荐)声明集合时,通过泛型可以指定集合中应该存储什么类型的元素(推荐)注意:需要存储基本数据类型时,使用其......
  • JavaWeb-JSP-JSTL c foreach -2023-04-09
    <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%><%@pageimport="java.util.ArrayList"%><%@pagecontentType="text/html;charset=UTF-8"language="java"%><html>&l......
  • JavaWeb-JSP JSTL标签 -2023-04-09
    <%--CreatedbyIntelliJIDEA.User:AdministratorDate:2023/4/9Time:15:10TochangethistemplateuseFile|Settings|FileTemplates.--%><%@pagecontentType="text/html;charset=UTF-8"language="java"%>&l......
  • 【Java 并发】【十】【JUC数据结构】【三】LinkedBlockingQueue阻塞队列原理
    1 前言这节我们就来看看LinkedBlockingQueue内部实现的原理。2 LinkedBlockingQueue的使用在看原理之前我们先来用一用LinkedBlockingQueue,来体验一下:2.1  插入数据publicclassLinkedBlockingQueueTest{publicstaticvoidmain(String[]args)throwsInter......