Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javet v0.9.1 #47

Merged
merged 13 commits into from
Jun 15, 2021
Merged
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,22 @@ Maven
<dependency>
<groupId>com.caoccao.javet</groupId>
<artifactId>javet</artifactId>
<version>0.9.0</version>
<version>0.9.1</version>
</dependency>

Gradle Kotlin DSL
^^^^^^^^^^^^^^^^^

.. code-block:: kotlin

implementation("com.caoccao.javet:javet:0.9.0")
implementation("com.caoccao.javet:javet:0.9.1")

Gradle Groovy DSL
^^^^^^^^^^^^^^^^^

.. code-block:: groovy

implementation 'com.caoccao.javet:javet:0.9.0'
implementation 'com.caoccao.javet:javet:0.9.1'

Hello Javet
-----------
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repositories {
}

group = "com.caoccao.javet"
version = "0.9.0"
version = "0.9.1"

repositories {
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion cpp/build.cmd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@echo off
REM Usage for V8: build -DV8_DIR=C:\v8
REM Usage for Node: build -DNODE_DIR=C:\node
SET JAVET_VERSION=0.9.0
SET JAVET_VERSION=0.9.1
rd /s/q build
mkdir build
cd build
Expand Down
2 changes: 1 addition & 1 deletion cpp/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Usage for V8: build -DV8_DIR=~/v8
# Usage for Node: build -DNODE_DIR=~/node
JAVET_VERSION=0.9.0
JAVET_VERSION=0.9.1
rm -rf build
mkdir build
cd build
Expand Down
58 changes: 40 additions & 18 deletions cpp/jni/com_caoccao_javet_interop_V8Native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,24 @@
namespace Javet {
#ifdef ENABLE_NODE
namespace NodeNative {
static jclass jclassV8Host;
static jmethodID jmethodIDV8HostIsLibraryReloadable;

static std::shared_ptr<node::ArrayBufferAllocator> GlobalNodeArrayBufferAllocator;

void Dispose() {
GlobalNodeArrayBufferAllocator.reset();
void Dispose(JNIEnv* jniEnv) {
if (!jniEnv->CallStaticBooleanMethod(jclassV8Host, jmethodIDV8HostIsLibraryReloadable)) {
GlobalNodeArrayBufferAllocator.reset();
}
}

void Initialize(JNIEnv* jniEnv) {
GlobalNodeArrayBufferAllocator = node::ArrayBufferAllocator::Create();
jclassV8Host = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/interop/V8Host"));
jmethodIDV8HostIsLibraryReloadable = jniEnv->GetStaticMethodID(jclassV8Host, "isLibraryReloadable", "()Z");

if (!GlobalNodeArrayBufferAllocator) {
GlobalNodeArrayBufferAllocator = node::ArrayBufferAllocator::Create();
}
}
}
#endif
Expand All @@ -62,15 +72,20 @@ namespace Javet {
static std::unique_ptr<V8Platform> GlobalV8Platform;
#endif

static jclass jclassV8Host;
static jmethodID jmethodIDV8HostIsLibraryReloadable;

static jclass jclassV8ValueInteger;
static jmethodID jmethodIDV8ValueIntegerToPrimitive;

static jclass jclassV8ValueString;
static jmethodID jmethodIDV8ValueStringToPrimitive;

void Dispose() {
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
void Dispose(JNIEnv* jniEnv) {
if (!jniEnv->CallStaticBooleanMethod(jclassV8Host, jmethodIDV8HostIsLibraryReloadable)) {
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
}
}

/*
Expand All @@ -79,6 +94,8 @@ namespace Javet {
or runtime memory corruption will take place.
*/
void Initialize(JNIEnv* jniEnv) {
jclassV8Host = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/interop/V8Host"));
jmethodIDV8HostIsLibraryReloadable = jniEnv->GetStaticMethodID(jclassV8Host, "isLibraryReloadable", "()Z");

jclassV8ValueInteger = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueInteger"));
jmethodIDV8ValueIntegerToPrimitive = jniEnv->GetMethodID(jclassV8ValueInteger, JAVA_METHOD_TO_PRIMITIVE, "()I");
Expand All @@ -90,21 +107,26 @@ namespace Javet {
#ifdef ENABLE_I18N
v8::V8::InitializeICU();
#endif
#ifdef ENABLE_NODE
uv_setup_args(0, nullptr);
std::vector<std::string> args{ "" };
std::vector<std::string> execArgs{ "" };
std::vector<std::string> errors;
int errorCode = node::InitializeNodeWithArgs(&args, &execArgs, &errors);
if (errorCode != 0) {
LOG_ERROR("Failed to call node::InitializeNodeWithArgs().");
if (Javet::V8Native::GlobalV8Platform) {
LOG_INFO("V8::Initialize() is skipped.");
}
Javet::V8Native::GlobalV8Platform = node::MultiIsolatePlatform::Create(4);
else {
#ifdef ENABLE_NODE
uv_setup_args(0, nullptr);
std::vector<std::string> args{ "" };
std::vector<std::string> execArgs{ "" };
std::vector<std::string> errors;
int errorCode = node::InitializeNodeWithArgs(&args, &execArgs, &errors);
if (errorCode != 0) {
LOG_ERROR("Failed to call node::InitializeNodeWithArgs().");
}
Javet::V8Native::GlobalV8Platform = node::MultiIsolatePlatform::Create(4);
#else
Javet::V8Native::GlobalV8Platform = v8::platform::NewDefaultPlatform();
Javet::V8Native::GlobalV8Platform = v8::platform::NewDefaultPlatform();
#endif
v8::V8::InitializePlatform(Javet::V8Native::GlobalV8Platform.get());
v8::V8::Initialize();
v8::V8::InitializePlatform(Javet::V8Native::GlobalV8Platform.get());
v8::V8::Initialize();
}
LOG_INFO("V8::Initialize() ends.");
}
}
Expand Down
16 changes: 8 additions & 8 deletions cpp/jni/com_caoccao_javet_interop_V8Native.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions cpp/jni/javet_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,19 @@ jint JNI_OnLoad(JavaVM* javaVM, void* reserved) {

void JNI_OnUnload(JavaVM* javaVM, void* reserved) {
LOG_INFO("JNI_OnUnload() begins.");
JNIEnv* jniEnv;
if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_8) != JNI_OK) {
LOG_ERROR("Failed to call JavaVM.GetEnv().");
}
if (jniEnv == nullptr) {
LOG_ERROR("Failed to get JNIEnv.");
}
else {
#ifdef ENABLE_NODE
Javet::NodeNative::Dispose();
Javet::NodeNative::Dispose(jniEnv);
#endif
Javet::V8Native::Dispose();
Javet::V8Native::Dispose(jniEnv);
}
LOG_INFO("JNI_OnUnload() ends.");
}

4 changes: 2 additions & 2 deletions cpp/jni/javet_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@ namespace Javet {

#ifdef ENABLE_NODE
namespace NodeNative {
void Dispose();
void Dispose(JNIEnv* jniEnv);
void Initialize(JNIEnv* jniEnv);
}
#endif

namespace V8Native {
void Dispose();
void Dispose(JNIEnv* jniEnv);
void Initialize(JNIEnv* jniEnv);
}
}
2 changes: 2 additions & 0 deletions cpp/jni/javet_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#pragma warning(disable: 4275)
#pragma warning(disable: 4251)
// #define NODE_WANT_INTERNALS 1
// #include <node_binding.h>
#include <node.h>
#include <uv.h>
#pragma warning(default: 4275)
Expand Down
12 changes: 6 additions & 6 deletions cpp/jni/javet_resource_node.rc
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,0,0
PRODUCTVERSION 0,9,0,0
FILEVERSION 0,9,1,0
PRODUCTVERSION 0,9,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -79,12 +79,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "caoccao.com"
VALUE "FileDescription", "caoccao.com"
VALUE "FileVersion", "0.9.0.0"
VALUE "InternalName", "libjavet-node-windows-x86_64.v.0.9.0.dll"
VALUE "FileVersion", "0.9.1.0"
VALUE "InternalName", "libjavet-node-windows-x86_64.v.0.9.1.dll"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "libjavet-node-windows-x86_64.v.0.9.0.dll"
VALUE "OriginalFilename", "libjavet-node-windows-x86_64.v.0.9.1.dll"
VALUE "ProductName", "Javet Windows"
VALUE "ProductVersion", "0.9.0.0"
VALUE "ProductVersion", "0.9.1.0"
END
END
BLOCK "VarFileInfo"
Expand Down
12 changes: 6 additions & 6 deletions cpp/jni/javet_resource_v8.rc
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,0,0
PRODUCTVERSION 0,9,0,0
FILEVERSION 0,9,1,0
PRODUCTVERSION 0,9,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -79,12 +79,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "caoccao.com"
VALUE "FileDescription", "caoccao.com"
VALUE "FileVersion", "0.9.0.0"
VALUE "InternalName", "libjavet-v8-windows-x86_64.v.0.9.0.dll"
VALUE "FileVersion", "0.9.1.0"
VALUE "InternalName", "libjavet-v8-windows-x86_64.v.0.9.1.dll"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "libjavet-v8-windows-x86_64.v.0.9.0.dll"
VALUE "OriginalFilename", "libjavet-v8-windows-x86_64.v.0.9.1.dll"
VALUE "ProductName", "Javet Windows"
VALUE "ProductVersion", "0.9.0.0"
VALUE "ProductVersion", "0.9.1.0"
END
END
BLOCK "VarFileInfo"
Expand Down
6 changes: 3 additions & 3 deletions docs/development/design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ Javet supports both Node.js mode and V8 mode both of which can co-exist in one J
.. image:: ../resources/images/javet_modes.png?raw=true
:alt: Javet Modes

As the diagram shows, Javet loads V8 v8.9+ in the default classloader as an out-of-box solution. Node.js is lazy loaded in a custom classloader. Detailed comparisons are as following.
As the diagram shows, both Node.js and V8 are lazy loaded in dedicated custom classloaders. Detailed comparisons are as following.

=========================== ======================= ==============================
Feature Node.js Mode V8 Mode
=========================== ======================= ==============================
Built-in No **Yes**
Lazy Loadable **Yes** **Yes**
Customization **High** **High**
Node.js Ecosystem **Complete** No
Security Low **High**
Unload Potentially Yes No
Unload **Yes** **Yes**
V8 Ecosystem **Complete** **Complete**
V8 Version Low **High**
=========================== ======================= ==============================
Expand Down
2 changes: 1 addition & 1 deletion docs/development/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ For now, Gradle v6.7 + Kotlin DSL constructs the build system.
Node.js
=================

Node.js 14.16.1+ is supported.
Node.js 14.17.0+ is supported.

Maven (Optional)
================
Expand Down
1 change: 1 addition & 0 deletions docs/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Javet Reference
* `Lock <lock.rst>`_
* `Termination <termination.rst>`_
* `Logging <logging.rst>`_
* `Load and Unload <load_and_unload.rst>`_
* `Best Practices <best_practices.rst>`_
* `Performance <performance.rst>`_
* `Error Codes <error_codes.rst>`_
Expand Down
47 changes: 47 additions & 0 deletions docs/reference/load_and_unload.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
===============
Load and Unload
===============

As documented in `design <../development/design.rst>`_, Javet supports loading and unloading the JNI libraries during runtime in both Node.js and V8 modes.

How?
====

Unload
------

Assuming the JNI library per mode is already loaded, here are the step-by-step on how to unload it.

.. code-block:: java

// Step 1: Set library reloadable. Why? Because Javet defaults that switch to false.
V8Host.setLibraryReloadable(true);
// Step 2: Get V8Host per JS runtime type.
V8Host v8Host = V8Host.getInstance(jsRuntimeType);
// Step 3: Unload the library.
v8Host.unloadLibrary();
// Step 4: Restore the switch.
V8Host.setLibraryReloadable(false);

How does ``unloadLibrary()`` work? There is no API that allows unloading a JNI library explicitly. The only way is GC will automatically unload the library if all references to that library are garbage collectable. So, application is supposed to close all V8 values, V8 runtimes prior to calling ``unloadLibrary()``.

Load
----

Assuming the JNI library per mode is already unloaded, here are the step-by-step on how to load it again.

.. code-block:: java

// Step 1: Get V8Host per JS runtime type.
V8Host v8Host = V8Host.getInstance(jsRuntimeType);
// Step 2: Load the library.
v8Host.loadLibrary();

Notes
=====

* ``unloadLibrary()`` can only take effect after all references are garbage collectable.
* ``loadLibrary()`` is internally called by Javet in the first time and only takes effect after ``unloadLibrary()`` is called.
* ``loadLibrary()`` and ``unloadLibrary()`` are for experiment only. **They may be unstable and crash JVM. Please use this feature at your own risk.**

[`Home <../../README.rst>`_] [`Javet Reference <index.rst>`_]
6 changes: 6 additions & 0 deletions docs/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Release Notes
=============

0.9.1
-----

* Moved V8 to a custom classloader
* Enabled ``unloadLibrary()`` and ``loadLibrary()`` in ``V8Host``

0.9.0
-----

Expand Down
Binary file modified docs/resources/images/javet_modes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading