Open-source project
mozilla/rhino avatar
mozilla/rhino

Rhino: JavaScript in Java, module by module

Rhino is an open-source implementation of JavaScript written entirely in Java

4,632 stars935 forksJavaScriptNOASSERTION

At a glance

What is it?
Mozilla's Rhino runs JavaScript inside the JVM and is now split into rhino, rhino-tools, rhino-xml, rhino-engine and rhino-all. The split matters more than the language coverage: it decides what your embedder can reach.
Who is it for?
Adopt Rhino when you want JavaScript evaluated inside a JVM process and you can accept the module split as a security boundary: depend on rhino alone unless you need the shell, E4X or ScriptEngine. Skip it if your scripts assume current ECMAScript or Node APIs; check the compatibility table and the release notes before committing, and verify whether rhino-tools is on your classpath at all, because that is the module that opens files and launches programs.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Who embeds a JavaScript engine in a JVM, and why Rhino is still one answer

Rhino is an implementation of JavaScript written in Java. That single sentence defines both its audience and its limits. It is for people who already have a JVM process and want to evaluate JavaScript inside it, not for people who want to run a JavaScript program as a process. The README points at script builders and embedders as the two groups the documentation serves, and the USAGE.md file lists projects that already use it.

The practical case is configuration and extension logic. A Java service needs user-supplied expressions, small rules, or plugin code, and shipping a second runtime is not acceptable. Rhino gives that service an evaluator that lives in the same heap and the same classpath, so values cross the boundary as Java objects rather than as serialized text.

The cost is that you are not getting a browser engine. The README links a compatibility table that shows which advanced features from ES6 and ES2016+ are implemented, which is an admission that coverage is partial and tracked feature by feature. Anyone who needs current ECMAScript should read that table before writing code, not after.

The module split is the real architecture decision

Through Rhino 1.7.15 the project was primarily distributed as one JAR, rhino.jar. Releases after that organize the code as Java modules, and the README is explicit that this changes what ends up in your dependency graph.

The rhino module is the primary codebase, necessary and sufficient to run JavaScript. Everything that uses Rhino needs it. In releases after 1.7.15 it does not contain the tools or the XML implementation. That is a deliberate reduction: the core evaluator no longer carries the shell and the file-loading machinery.

rhino-tools adds the shell, the debugger, and the Global object. The README warns that Global gives Rhino the ability to print to stdout, open files, and do other things that may be dangerous in a sensitive environment, so it only makes sense to include if you will use it. That is the sharpest sentence in the document. If your service evaluates untrusted input, the presence of rhino-tools on the classpath is a security decision, not a convenience.

rhino-xml adds the E4X XML implementation and is only required if you use that standard. rhino-engine adds the standard Java ScriptEngine implementation, and the README is openly unenthusiastic about it: for anything even moderately complex it says using Rhino's API directly is almost always easier and always more flexible. rhino-all builds an all-in-one JAR containing rhino-runtime, rhino-tools and rhino-xml, which is what you use if you want to run Rhino with java jar. There is also rhino-kotlin for Kotlin support.

The recommendation section goes further and suggests many applications need nothing but the main rhino module. The alternative offered for Global's handy built-ins is that rhino includes an implementation of the console object. So the project's own position is: take the core, skip the tools, and use console instead of print and load.

Installing Rhino and running a first script

Rhino requires Java 17 or higher to run and Java 21 or higher to build, with Java 25 recommended. The README's build path is Gradle. To build and run a shell from a checkout, the documented command is:

bash
./gradlew run -q --console=plain

That drops you into the Rhino shell. There is no separate install step in the README, so a first run means either building from source this way or pulling the published artifacts from Maven Central, which the README implies when it says which modules are published there and which are not. The tests module, it-android, benchmarks and examples are not published.

If you want to run the test suite from a checkout, the README gives a submodule step first, because the tests pull in external suites including the Mozilla legacy test scripts and test262:

bash
git submodule init
git submodule update
./gradlew check

For embedding, the README's guidance is to depend on the rhino module and add others only when needed. It does not print a dependency coordinate in the text reproduced here, so check the release artifacts rather than copying a version string from an article. What the README does state is that the current release is Rhino 1.9.1, published on February 15, 2026, and that the release notes live in RELEASE-NOTES.md.

The build has one wrinkle worth knowing before you file a bug: the spotless tool, which enforces code formatting, will not run on older Java versions and emits a warning instead. The build tools use the --release flag so the product only uses Java 17 features, and CI runs the tests on Java 17, 21 and 25.

Where Rhino is the wrong tool

The compatibility table is the first limitation, and it is self-declared. The README links it specifically to show which advanced JavaScript features from ES6 and ES2016+ are implemented. A feature-by-feature table implies gaps. If your script uses a modern language construct that Rhino has not implemented, you find out at parse or run time, not at review time.

The second limitation is the Global object. Because rhino-tools carries functionality to launch programs and load files, an embedder that includes it for the convenience of print and load has widened what evaluated code can do. The README frames this as something that may be considered dangerous in a sensitive environment. There is no documented sandbox mode in the text here that makes Global safe; the documented mitigation is not to include the module.

The third is the ScriptEngine route. Java's ScriptEngine interface is described as a strange abstraction that does not necessarily map well to Rhino. Choosing it to keep engine-swapping options open costs you flexibility on the Rhino side, and the README's own advice is to use the API directly for anything beyond moderate complexity.

Finally, release cadence is uneven. There were long gaps historically: 1.7.14 in January 2022, then 1.7.15 in May 2024. The recent sequence is tighter, with 1.8.1 on December 2, 2025, 1.9.0 on December 22, 2025, and 1.9.1 on February 15, 2026, and the last push to the repository was on 2026-09-21. That is current activity, but the older gaps are a reminder that a pinned version can sit for a long time.

GraalJS and Nashorn as the comparison points

The nearest alternative for JVM embedding is GraalJS, which takes a different route: it is built on GraalVM's compiler infrastructure and targets current ECMAScript conformance rather than a tracked partial subset. The difference in approach shows up in deployment. Rhino is plain Java, requires Java 17 to run, and the README's build guidance is Gradle with the --release flag. GraalJS pulls you toward GraalVM as the runtime or a more involved setup on a standard JDK.

Nashorn is the other reference point, and Rhino's own README treats it indirectly through the ScriptEngine interface, which Nashorn also implemented. Nashorn was deprecated and removed from the JDK, which is part of why a standalone JavaScript engine in Java remains a live question. Rhino's answer is to keep the engine as an ordinary library with an optional ScriptEngine adapter in a separate module, so projects that used the ScriptEngine abstraction can keep that shape while depending on Rhino.

The honest summary: if you need broad modern JavaScript, Rhino's compatibility table is the thing to read first, and it may send you elsewhere. If you need a small Java-native evaluator with a module boundary you can control, Rhino's split is the feature, not the packaging detail.

Maintenance, licence and upgrade cost

Rhino is not archived. The last push was on 2026-09-21, and the most recent release is Rhino 1.9.1 from February 15, 2026. The release history shows the project moving again after the 2022 to 2024 gap, with three releases between December 2025 and February 2026.

Upgrading across the 1.7.15 boundary is the expensive part. Before that line, Rhino was primarily used as a single rhino.jar. After it, the code is organized as Java modules and the core no longer contains tools or XML. An application that relied on the old single JAR getting print, load or E4X for free has to add rhino-tools or rhino-xml explicitly, and adding rhino-tools means accepting the file and program launching capability that comes with Global. A version bump is therefore also a dependency review. The README's own recommendation to depend on rhino alone is the cheap path, but it only works if nothing in your scripts needs the extras.

On licensing: the README states Rhino is licensed under MPL 2.0, and the repository carries LICENSE.txt. The NOASSERTION label on the repository metadata does not match the README's plain statement, so treat LICENSE.txt as the authoritative file and have your own counsel read it. MPL 2.0 is a file-level copyleft licence, which is a different shape from permissive licences, and how that interacts with your distribution model is a question for a lawyer rather than for this article.

Editorial conclusion

Adopt Rhino when you want JavaScript evaluated inside a JVM process and you can accept the module split as a security boundary: depend on rhino alone unless you need the shell, E4X or ScriptEngine. Skip it if your scripts assume current ECMAScript or Node APIs; check the compatibility table and the release notes before committing, and verify whether rhino-tools is on your classpath at all, because that is the module that opens files and launches programs.

Frequently asked questions

What Java version does Rhino need?

Rhino requires Java 17 or higher to run and Java 21 or higher to build, and the README says Java 25 is highly recommended. The build tools use the --release flag so the product only uses Java 17 features, and CI runs tests on Java 17, 21 and 25.

Which Rhino module should I depend on for embedding?

The README recommends depending on the rhino module alone for many applications, since it is necessary and sufficient to run JavaScript. Add rhino-tools only if you need the shell, debugger or Global object, and note that Global can print to stdout, open files and launch programs.

Does Rhino support modern JavaScript features?

The README links a compatibility table showing which advanced features from ES6 and ES2016+ are implemented, which indicates coverage is tracked feature by feature rather than complete. Check that table against the constructs your scripts use before adopting it.

What licence is Rhino released under?

The README states Rhino is licensed under MPL 2.0 and the repository contains LICENSE.txt. Repository metadata labels the licence as NOASSERTION, so read LICENSE.txt rather than relying on the metadata field.

How do I run the Rhino shell from a source checkout?

The README gives ./gradlew run -q --console=plain to build and run a Rhino shell. To run the tests you first run git submodule init and git submodule update, then ./gradlew check.

Official sources

  1. Issues
  2. mozilla/rhino on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mozilla-rhino.svg)](https://hysenlabs.com/projects/mozilla-rhino)