Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
java-bridge
Advanced tools
A bridge between Node.js programs and Java APIs written in Rust using napi-rs to provide a fast and memory-safe interface between the two languages.
The pre-compiled binaries will be provided with the package, the only thing
you need to do on your machine is install a Java Runtime Environment (JRE)
for this package to use. In contrast to other node.js <-> java
interfaces,
the binary is not hard linked to the JDK it has been compiled with but rather
loads the jvm native library dynamically when the program first starts up.
The full documentation of this package is available here.
NOTE: As of version 2.1.0
, this package has been renamed from @markusjx/java
to java-bridge
.
npm i java-bridge
This is only required for development purposes. When installing the package using npm i
, you can skip this.
In order to build this project, you should install
Then, to build the project, run:
npm install
npm run build
✅ = Pre-compiled binaries are available
-
= Pre-compiled binaries are not available
Operating System | i686 | x64 | arm | arm64 |
---|---|---|---|---|
Linux | - | ✅ | - | ✅ |
Windows | ✅ | ✅ | - | - |
macOS | - | ✅ | - | ✅ |
import { importClass } from './java-bridge';
const System = importClass('java.lang.System');
System.out.println('Hello world!');
Create a new Java VM using the ensureJvm
method.
Calling this after the jvm has already been created will do nothing.
Destroying the jvm manually is not (yet) supported.
This will first search for a suitable jvm
native library on the system and then
start the jvm with no extra options. This is also called when any call to the jvm is made
but the jvm is not yet started.
import { ensureJvm } from 'java-bridge';
ensureJvm();
You can pass extra options to the jvm when creating it, for example requesting a specific jvm version, specifying the location of the jvm native library or passing additional arguments to the jvm.
import { ensureJvm, JavaVersion } from 'java-bridge';
ensureJvm({
libPath: 'path/to/jvm.dll',
version: JavaVersion.VER_9,
opts: '-Xms512m -Xmx512m',
});
By default, new threads will not be attached as daemon threads, meaning any thread attached to the jvm will be automatically detached once it is not required anymore. This slows down asynchronous calls but will prevent the jvm from being terminated if any thread is still running.
If you want to change this behaviour, you can pass the useDaemonThreads
option to the ensureJvm
function.
This will make the jvm attach threads as daemon threads causing those threads to not be detached
once not required anymore.
ensureJvm({
useDaemonThreads: true,
});
When using this package in a packaged electron application, you should unpack this package and
the appropriate binaries for your platform into the app.asar.unpacked
folder. When using
electron-builder, you can do this by adding the following to your package.json
:
{
"build": {
"asarUnpack": [
"node_modules/java-bridge/**",
"node_modules/java-bridge-*/**"
]
}
}
Additionally, you should set the isPackagedElectron
option to true
when creating the jvm:
ensureJvm({
isPackagedElectron: true,
});
This option should not have any effect when not using electron or not having the application packaged.
In order to import your own classes into the node environment, you need
to add the JAR file to the class path. You can do that with the
appendClasspath
or classpath.append
methods. After loading a JAR, you can import classes from it like any other class
from the JVM using importClass
or importClassAsync
.
import { appendClasspath } from 'java-bridge';
// Append a single jar to the class path
appendClasspath('/path/to/jar.jar');
// Append multiple jars to the class path
appendClasspath(['/path/to/jar1.jar', '/path/to/jar2.jar']);
or
import { classpath } from 'java-bridge';
// Append a single jar to the class path
classpath.append('/path/to/jar.jar');
If you want to use Java APIs in a synchronous way, you can use the synchronous API of this module. Any call to the Java API will be executed in the same thread as your node process so this may cause your program to hang until the execution is finished. But - in contrast to the asynchronous API - these calls are a lot faster as no extra threads need to be created/attached to the JVM.
All synchronous java methods are proceeded with the postfix Sync
.
This means, all methods of a class (static and non-static) are generated twice,
once as a synchronous call and once as an asynchronous call.
If you are looking for asynchronous calls, take a look at the next section.
In order to import a class synchronously, you can use the importClass
function.
Using this method does not affect your ability to call any method of the class asynchronously.
import { importClass } from 'java-bridge';
// Import a class
const JString = importClass('java.lang.String');
// Create a new instance of the class
const str = new JString('Hello World');
// Call a method on the instance
str.lengthSync(); // 11
// Supported native types will be automatically converted
// to the corresponding type in the other language
str.toStringSync(); // 'Hello World'
If you want to use Java APIs in an asynchronous way, you can use the asynchronous API of this module. Any call to the Java API will be executed in a separate thread and the execution will not block your program. This is in general a lot slower as the synchronous API but allows the program to run more smoothly.
If you want to improve the performance of the asynchronous API, you can force the module to attach any thread as a daemon thread to the JVM. This allows the program to not constantly attach new threads to the JVM as the old ones can be reused and thus improves the performance.
In order to import a class asynchronously, you can use the
importClassAsync
function.
import { importClassAsync } from 'java-bridge';
const JString = await importClassAsync('java.lang.String');
// Create a new instance asynchrnously using 'newInstanceAsync'
const str = await JString.newInstanceAsync('Hello World');
// Call methods asynchronously
await str.length(); // 11
await str.toString(); // 'Hello World'
You can also implement a Java interface in node.js using the
newProxy
method.
Please note that when calling a java method that uses an interface defined by this method,
you must call that method using the interface asynchronously as Node.js is single threaded
and can't wait for the java method to return while calling the proxy method at the same time.
import { newProxy } from 'java-bridge';
const proxy = newProxy('path.to.MyInterface', {
// Define methods...
});
// Do something with the proxy
instance.someMethod(proxy);
// Destroy the proxy
proxy.reset();
If you want to redirect the stdout and/or stderr from the java
process to the node.js process, you can use the
enableRedirect
method.
import { stdout } from 'java-bridge';
const guard = stdout.enableRedirect(
(_, data) => {
console.log('Stdout:', data);
},
(_, data) => {
console.error('Stderr:', data);
}
);
string
, number
, boolean
or BigInt
may be passed to methods accepting matching
typesstring
values will always be converted to java.lang.String
string
values with just one character may be converted to char
or java.lang.Char
if requiredchar
to a java method, use a string
containing just one characternumber
values will be converted to int
, long
, double
, float
, java.lang.Integer
,
java.lang.Long
, java.lang.Double
or java.lang.Float
depending on the type the java function to call requiresboolean
values will be converted to either boolean
or java.lang.Boolean
BigInt
values will be converted to either long
or java.lang.Long
java.lang.String
values will be converted to string
int
, double
, float
, java.lang.Integer
, java.lang.Double
or java.lang.Float
values will be converted to number
long
or java.lang.Long
values will always be converted to BigInt
boolean
or java.lang.Boolean
values will be converted to boolean
char
or java.lang.Character
values will be converted to string
Buffer
and vice-versaThis module also ships with a command line interface called java-ts-gen
for creating typescript definitions for Java classes.
The command line interface will create typescript definitions for all specified classes and their dependencies.
npm install -g java-bridge
java-ts-gen <output> <classnames..>
Positionals:
classnames The fully qualified class name(s) to convert [string]
output The output file [string]
Options:
--help Show help [boolean]
--version Show version number [boolean]
--classpath, --cp The classpath to use [string]
Generate definitions for the java.lang.String
class and all its referenced classes and save them to ./project
:
java-ts-gen ./project java.lang.String
This will create a directory called java
containing the definitions for the java.lang.String
class and all its
dependencies all inside subdirectories. The java.lang.String
class will be saved to ./project/java/lang/String.ts
.
Thus, the folder structure of project
will look something like this:
.
├── ...
├── java
│ ├── lang
│ │ ├── String.ts
│ │ ├── Object.ts
│ │ └── ...
│ ├── util
│ │ └── ...
│ └── ...
└── ...
Generate definitions for the java.lang.String
and java.util.ArrayList
classes and all of their dependencies
and save them to ./project
:
java-ts-gen ./project java.lang.String java.util.ArrayList
FAQs
A bridge between Node.js and Java APIs
The npm package java-bridge receives a total of 539 weekly downloads. As such, java-bridge popularity was classified as not popular.
We found that java-bridge demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.