highlight.js

Monday, February 22, 2021

Javet Design

Architecture

Javet Architecture

Primitive and Reference Types in Javet

There is a vague boundary between V8 primitive and reference types. In Javet, the definition of primitive is a mixture of both V8 and Java primitive types as a trade-off in design.

FeaturePrimitiveReference
InterceptionNoYes
Memory CopyCopy by ValueCopy by Reference
Resource LeakNot PossiblePossible
Set to WeakNoYes

Reference typed objects keep memory footprint in V8 + JNI + JVM. All resource will be recycled when close() is called. That is quite an old school way of managing resource. Javet tries to hide that kind of tedious work from Java applications via try-with-resource.

Please refer to Best Practices for detail.

Engine Pool

Javet Engine Pool

V8 Isolate and Context in Javet

Getting started with embedding V8 is an excellent article that explains the concepts, design, insights of V8. In summary:

  • An isolate is a VM instance with its own heap.
  • A context is an execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8.

In Javet, that model is simplified to 1 engine - 1 runtime - 1 isolate - 1 context. In V8Runtime, resetIsolate() and resetContext() are both exposed. It is recommended to always use resetContext() to get a brand new V8 context for the following reasons.

  • resetContext() is a much cheaper operation with much better performance.
  • resetContext() is good enough in terms of getting a brand new V8 context.

Javet Engine Pool

Multiple Javet engines are managed by Javet Engine Pool which works almost the same way as a typical DB connection pool. Javet Engine Pool is thread-safe. However, Javet Engine is NOT thread-safe because it is designed to be single-threaded and lock free for the following reasons.

  • V8 isolate and V8 context are single-threaded. Thread context violation results in V8 core dump immediately.
  • Javet Engine performs better without locks. Actually, Javet engine only validates current thread ID to minimize the performance overhead.

Please refer to Best Practices for detail.

Saturday, February 20, 2021

Javet v0.7.3

Javet v0.7.3 is released with the majority of features I expect. Let's walk through it via a few sample code snippets.

1. Dependency

Maven

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

Gradle Kotlin DSL

implementation("com.caoccao.javet:javet:0.7.3")

Gradle Groovy DSL

 implementation 'com.caoccao.javet:javet:0.7.3'

2. Samples

Hello Javet 

// Step 1: Create a V8 runtime from V8 host in try resource.
try (V8Runtime v8Runtime = V8Host.getInstance().createV8Runtime()) {
    // Step 2: Execute a string as JavaScript code and print the result to console.
    System.out.println(v8Runtime.getExecutor("'Hello Javet'").executeString()); // Hello Javet
    // Step 3: Resource is recycled automatically at the end of the try resource block.
}

Print 1 + 1

// Step 1: Create a V8 runtime from V8 host in try resource.
try (V8Runtime v8Runtime = V8Host.getInstance().createV8Runtime()) {
    // Step 2: Execute a string as JavaScript code and print the result to console.
    System.out.println("1 + 1 = " + v8Runtime.getExecutor("1 + 1").executeInteger()); // 2
    // Step 3: Resource is recycled automatically at the end of the try resource block.
}

Play with Pool and Console

// Create a Javet engine pool.
try (IJavetEnginePool javetEnginePool = new JavetEnginePool()) {
    // Get a Javet engine from the pool.
    try (IJavetEngine javetEngine = javetEnginePool.getEngine()) {
        // Get a V8 runtime from the engine.
        V8Runtime v8Runtime = javetEngine.getV8Runtime();
        // Create a Javet console interceptor.
        JavetConsoleInterceptor javetConsoleInterceptor = new JavetConsoleInterceptor(v8Runtime);
        // Register the Javet console to V8 global object.
        javetConsoleInterceptor.register(v8Runtime.getGlobalObject());
        // V8 console log is redirected to JVM console log.
        v8Runtime.getExecutor("console.log('Hello Javet from Pool');").executeVoid();
        // Unregister the Javet console to V8 global object.
        javetConsoleInterceptor.unregister(v8Runtime.getGlobalObject());
        // close() is not necessary because the Javet pool handles that.
    }
} 

You are welcome visiting https://github.com/caoccao/Javet/ for more detail. 

IDEA / HandBrake / WSL Port Conflict

Recently I upgraded HandBrake to the latest version, however, it stopped working. The root cause is TCP port conflict. As usual, I ran net s...