Java Addon V8 Repack May 2026

Java V8 Repack Addon

Typical components

2. C++ Native Implementation

// v8repack.cpp
#include <jni.h>
#include <v8.h>
#include <libplatform/libplatform.h>
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>

using namespace v8;

// Structure to hold V8 state struct V8EngineState { std::unique_ptr<Platform> platform; Isolate* isolate; Global<Context> context;

V8EngineState() : isolate(nullptr) {}

};

// JNI function implementations extern "C"

JNIEXPORT jlong JNICALL Java_com_v8_repack_V8Repack_initV8(JNIEnv* env, jobject obj) V8EngineState* state = new V8EngineState(); java addon v8 repack

// Initialize V8 platform
state->platform = platform::NewDefaultPlatform();
V8::InitializePlatform(state->platform.get());
V8::Initialize();
// Create isolate
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = 
    ArrayBuffer::Allocator::NewDefaultAllocator();
state->isolate = Isolate::New(create_params);
// Create global context
Isolate::Scope isolate_scope(state->isolate);
    HandleScope handle_scope(state->isolate);
Local<Context> context = Context::New(state->isolate);
    state->context.Reset(state->isolate, context);
return reinterpret_cast<jlong>(state);

JNIEXPORT void JNICALL Java_com_v8_repack_V8Repack_destroyV8(JNIEnv* env, jobject obj, jlong handle) V8EngineState* state = reinterpret_cast<V8EngineState*>(handle); if (state) state->isolate->Dispose(); V8::Dispose(); V8::ShutdownPlatform(); delete state;

JNIEXPORT void JNICALL Java_com_v8_repack_V8Repack_setV8Flags(JNIEnv* env, jobject obj, jlong handle, jstring flags) V8EngineState* state = reinterpret_cast<V8EngineState*>(handle); if (!state) return;

const char* flags_str = env->GetStringUTFChars(flags, nullptr);
V8::SetFlagsFromString(flags_str, strlen(flags_str));
env->ReleaseStringUTFChars(flags, flags_str);

JNIEXPORT jbyteArray JNICALL Java_com_v8_repack_V8Repack_repackScript( JNIEnv* env, jobject obj, jlong handle, jbyteArray script, jobject dependencies)

V8EngineState* state = reinterpret_cast<V8EngineState*>(handle);
if (!state) return nullptr;
Isolate::Scope isolate_scope(state->isolate);
HandleScope handle_scope(state->isolate);
Local<Context> context = state->context.Get(state->isolate);
Context::Scope context_scope(context);
// Get script string
jsize script_len = env->GetArrayLength(script);
jbyte* script_bytes = env->GetByteArrayElements(script, nullptr);
std::string script_str(reinterpret_cast<char*>(script_bytes), script_len);
env->ReleaseByteArrayElements(script, script_bytes, JNI_ABORT);
// Build combined script with dependencies
std::string combined_script = "// Repacked V8 Script\n";
// Add dependencies as modules
if (dependencies != nullptr) 
    jclass mapClass = env->GetObjectClass(dependencies);
    jmethodID entrySetMethod = env->GetMethodID(mapClass, "entrySet", 
                                                 "()Ljava/util/Set;");
    jobject entrySet = env->CallObjectMethod(dependencies, entrySetMethod);
jclass setClass = env->GetObjectClass(entrySet);
    jmethodID iteratorMethod = env->GetMethodID(setClass, "iterator", 
                                                 "()Ljava/util/Iterator;");
    jobject iterator = env->CallObjectMethod(entrySet, iteratorMethod);
jclass iteratorClass = env->GetObjectClass(iterator);
    jmethodID hasNextMethod = env->GetMethodID(iteratorClass, "hasNext", "()Z");
    jmethodID nextMethod = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
jclass entryClass = env->FindClass("java/util/Map$Entry");
    jmethodID getKeyMethod = env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
    jmethodID getValueMethod = env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
while (env->CallBooleanMethod(iterator, hasNextMethod)) 
        jobject entry = env->CallObjectMethod(iterator, nextMethod);
        jstring key = (jstring)env->CallObjectMethod(entry, getKeyMethod);
        jbyteArray value = (jbyteArray)env->CallObjectMethod(entry, getValueMethod);
const char* key_str = env->GetStringUTFChars(key, nullptr);
        jsize value_len = env->GetArrayLength(value);
        jbyte* value_bytes = env->GetByteArrayElements(value, nullptr);
combined_script += "// Module: " + std::string(key_str) + "\n";
        combined_script += std::string(reinterpret_cast<char*>(value_bytes), value_len);
        combined_script += "\n\n";
env->ReleaseStringUTFChars(key, key_str);
        env->ReleaseByteArrayElements(value, value_bytes, JNI_ABORT);
// Add main script
combined_script += "// Main script\n";
combined_script += script_str;
// Compile and serialize the script
Local<String> source = String::NewFromUtf8(state->isolate, 
                                            combined_script.c_str(),
                                            NewStringType::kNormal)
                       .ToLocalChecked();
Local<Script> compiled_script;
if (!Script::Compile(context, source).ToLocal(&compiled_script)) 
    return nullptr;
// Serialize the compiled script
ScriptCompiler::CachedData* cache = ScriptCompiler::CreateCodeCache(
    compiled_script->GetUnboundScript());
// Create byte array to return
jbyteArray result = env->NewByteArray(cache->length);
env->SetByteArrayRegion(result, 0, cache->length, 
                        reinterpret_cast<jbyte*>(cache->data));
delete cache;
return result;

JNIEXPORT jbyteArray JNICALL Java_com_v8_repack_V8Repack_executeScript( JNIEnv* env, jobject obj, jlong handle, jbyteArray script)

V8EngineState* state = reinterpret_cast<V8EngineState*>(handle);
if (!state) return nullptr;
Isolate::Scope isolate_scope(state->isolate);
HandleScope handle_scope(state->isolate);
Local<Context> context = state->context.Get(state->isolate);
Context::Scope context_scope(context);
// Get script string
jsize script_len = env->GetArrayLength(script);
jbyte* script_bytes = env->GetByteArrayElements(script, nullptr);
std::string script_str(reinterpret_cast<char*>(script_bytes), script_len);
env->ReleaseByteArrayElements(script, script_bytes, JNI_ABORT);
// Try to deserialize first
ScriptCompiler::CachedData* cache = new ScriptCompiler::CachedData(
    reinterpret_cast<const uint8_t*>(script_str.c_str()), 
    script_str.length(),
    ScriptCompiler::CachedData::BufferNotOwned);
Local<Script> compiled_script;
TryCatch try_catch(state->isolate);
// Compile from cache or source
if (cache->rejected) 
    Local<String> source = String::NewFromUtf8(state->isolate, 
                                                script_str.c_str(),
                                                NewStringType::kNormal)
                           .ToLocalChecked();
if (!Script::Compile(context, source).ToLocal(&compiled_script)) 
        delete cache;
        return nullptr;
else 
    ScriptCompiler::Source source(cache);
    if (!ScriptCompiler::Compile(context, &source, 
                                 ScriptCompiler::kConsumeCodeCache)
         .ToLocal(&compiled_script)) 
        delete cache;
        return nullptr;
delete cache;
// Execute script
Local<Value> result;
if (!compiled_script->Run(context).ToLocal(&result)) 
    String::Utf8Value error(state->isolate, try_catch.Exception());
    return nullptr;
// Convert result to string
String::Utf8Value utf8(state->isolate, result);
std::string result_str(*utf8, utf8.length());
// Return as byte array
jbyteArray result_array = env->NewByteArray(result_str.length());
env->SetByteArrayRegion(result_array, 0, result_str.length(),
                        reinterpret_cast<const jbyte*>(result_str.c_str()));
return result_array;

// extern "C"

Building Your Own Custom Java Addon V8 Repack

If off-the-shelf solutions like J2V8 lack features or platform support, you may want to create your own repack. This is complex but doable:

  1. Clone Google’s V8 repository and build it using gn and ninja.
  2. Write JNI glue code to expose V8’s C++ API to Java.
  3. Compile the shared library (libv8_jni.so).
  4. Package the .so and the Java classes into a single JAR.

Tools to help: Use javah (or the modern native keyword in Panama) to generate headers, and consider using GraalVM Native Image for a different approach. Java V8 Repack Addon Typical components