V8 module(s) not recycled and V8 object(s) not recycled
Closed this issue · 5 comments
app/src/main/assets/js/sampledata/tasks/task_dy_toker.js
import { C270301 } from "version/27.3.0.js";
app/src/main/assets/js/sampledata/version/27.3.0.js
export const C290701 = {}
package top.deeke.script;
import android.content.Context;
import android.util.Log;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.caoccao.javet.exceptions.JavetCompilationException;
import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.exceptions.JavetExecutionException;
import com.caoccao.javet.exceptions.JavetScriptingError;
import com.caoccao.javet.exceptions.JavetTerminatedException;
import com.caoccao.javet.interop.V8Host;
import com.caoccao.javet.interop.V8Runtime;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import top.deeke.script.func.Asset;
import top.deeke.script.js.V8.V8Manager;
@RunWith(AndroidJUnit4.class)
public class JavetInstrumentedTest {
@rule
public ActivityScenarioRule activityRule = new ActivityScenarioRule<>(ScriptActivity.class);
private void loadModules(V8Runtime v8Runtime, Context context) {
v8Runtime.setV8ModuleResolver((runtime, resourceName, v8ModuleReferrer) -> {
Log.d("debug", resourceName + ":::" + v8Runtime);
try {
V8Manager.setType(1);
return runtime.getExecutor(V8Manager.getFileContent(context, resourceName)).setResourceName(resourceName).compileV8Module();
} catch (JavetCompilationException | JavetExecutionException | IOException e) {
throw new RuntimeException(e);
}
});
}
public String getFileContent(Context context, String filename) throws IOException {
return Asset.readFile(context, "js/sampledata/" + filename);
}
private static void closeByException(V8Runtime v8Runtime) {
try {
v8Runtime.removeV8Modules();//移除自定义的所有js模块
Log.d("debug", "模块清理完成");
java.lang.System.gc();
java.lang.System.runFinalization();
v8Runtime.lowMemoryNotification();
v8Runtime.close();
Log.d("debug", "成功关闭了哦");
} catch (JavetException e) {
Log.d("debug", "停止错误:" + e.getMessage());
}
}
@Test
public void recycleBug() {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
ActivityScenario<ScriptActivity> scenario = activityRule.getScenario();
scenario.onActivity(activity -> {
Path filePath = Paths.get("tasks/task_dy_toker.js");
V8Runtime v8Runtime = null;
try {
v8Runtime = V8Host.getV8Instance().createV8Runtime();
loadModules(v8Runtime, appContext);
try {
v8Runtime.getExecutor(getFileContent(appContext, filePath.toString())).setModule(true).setResourceName(filePath.toString()).executeVoid();
} catch (IOException err) {
Log.d("debug", "错误:" + err);
}
} catch (JavetTerminatedException e) {
Log.d("debug", "打断了:" + e.getMessage());
} catch (JavetExecutionException | JavetCompilationException e) {
JavetScriptingError err = e.getScriptingError();
Log.d("debug", "错误:" + err.toString());
} catch (JavetException er) {
Log.d("debug", "运行错误:" + Objects.requireNonNull(er.getMessage()));
} finally {
Log.d("debug", "中断了:");
closeByException(v8Runtime);
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
}
Could you please create a repo that reproduces the issue? I don't think it's related to Android development.
Could you please create a repo that reproduces the issue? I don't think it's related to Android development.
package top.deeke.script;//package top.deeke.script;
import com.caoccao.javet.exceptions.JavetCompilationException;
import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.exceptions.JavetExecutionException;
import com.caoccao.javet.interop.V8Host;
import com.caoccao.javet.interop.V8Runtime;
import org.junit.Test;
import java.io.IOException;
public class JavetUnit2Test {
private void loadModules(V8Runtime v8Runtime) {
v8Runtime.setV8ModuleResolver((runtime, resourceName, v8ModuleReferrer) -> {
try {
return runtime.getExecutor(getFileContent(resourceName)).setResourceName(resourceName).compileV8Module();
} catch (JavetCompilationException | JavetExecutionException | IOException e) {
throw new RuntimeException(e);
}
});
}
public String getFileContent(String filename) throws IOException {
return "export const Dy = {name: 'my name'}";//这里的逻辑写死
}
@Test
public void recycleBug() {
V8Runtime v8Runtime = null;
try {
v8Runtime = V8Host.getV8Instance().createV8Runtime();
loadModules(v8Runtime);
v8Runtime.getExecutor("import {Dy} from 'dy.js';Dy.name;").setModule(true).setResourceName("main.js").executeVoid();
} catch (JavetException ignored) {
} finally {
assert v8Runtime != null;
try {
v8Runtime.removeV8Modules();//移除自定义的所有js模块
System.gc();
System.runFinalization();
v8Runtime.lowMemoryNotification();
v8Runtime.close();
} catch (JavetException ignored) {
}
}
}
}
I'm expecting a github repo that I could check out and reproduce. The code you left is incomplete.
https://github.com/DeekeScript/javetTest
please pull this project and execute the unit testing inside
List<V8Module> modules = new ArrayList<>();
private void loadModules(V8Runtime v8Runtime) {
v8Runtime.setV8ModuleResolver((runtime, resourceName, v8ModuleReferrer) -> {
try {
V8Module v8Module = runtime.getExecutor(getFileContent(resourceName)).setResourceName(resourceName).compileV8Module();
modules.add(v8Module);
return v8Module;
} catch (JavetCompilationException | JavetExecutionException | IOException e) {
throw new RuntimeException(e);
}
});
}
I have found a solution to the problem. When loading the module, record it in the array. Before closing v8, just close the module
for(V8Module v8Module:this.modules){
v8Module.close();
}
System.gc();
System.runFinalization();
v8Runtime.lowMemoryNotification();