我知道读这么大的一篇文章有很多要求,但我希望你这样做,因为我真的不知道从哪里开始寻找一个解决我甚至不明白的问题的方法。
我在windows服务器上有一个java服务。此服务在启动时加载/评估多个javascript文件。这些javascript文件都有相同的结构,它们包含两个函数:process(name, content) { return { result: data } }和selfTest()。如果自测试成功,服务器加载脚本、计算脚本、检查重新分配的函数、运行自测试并将process函数的句柄存储在映射中(映射的关键是脚本执行的字段名):
// Called on MainThread
private static final String JS_FN_SELFTEST = "selfTest";
private static final String JS_FN_PROCESS = "process";
private final Map<String, Value> _cache;
private final Context _ctx;
public ScriptManager () {
_cache = new HashMap<>();
_ctx = Context.newBuilder("js").allowIO(true).build();
}
private void addScriptFile(Path fileName, String... fieldNames)
throws IOException, NoSuchMethodException {
var p = Path.of(fileName.toString());
var jsSource = Files.readString(p);
var evaluated = _ctx.eval("js", jsSource);
if (!evaluated.hasMember(JS_FN_SELFTEST)) {
throw new NoSuchMethodException(JS_FN_SELFTEST);
}
var fnSelfTest = evaluated.getMember(JS_FN_SELFTEST);
fnSelfTest.execute();
if (!evaluated.hasMember(JS_FN_PROCESS)) {
throw new NoSuchMethodException(JS_FN_PROCESS);
}
for(String column: fieldNames) {
_cache.put(column, evaluated.getMember(JS_FN_PROCESS));
}
}启动后,该服务监视一个网络共享文件删除。当一个文件丢失时,该文件将被读取和处理。数据将首先使用通用脚本进行清理,然后将处理映射中的部分字段。以下功能进行清洗,现场处理类似,问题也发生在那里.
// Called on JobProcessingThread
public List<Data> clean(DataMap dataSet) {
var modified = new ArrayList<Data>();
var fnProcess = _cache.get(ALL_COLUMNS_MARKER);
for(var key: dataSet.keyList()) {
var data = dataSet.get(key);
if (!data.Field.Scriptable) continue;
String oldContent = data.getContent();
if (oldContent == null) continue;
try {
var value = fnProcess.execute(data.SourceName, oldContent); // error occurs here
var map = value.as(Map.class);
var newContent = map.get("result").toString();
if (!oldContent.equals(newContent)) {
data.setContent(newContent);
modified.add(data);
}
} catch(PolyglotException pe) {
data.setProblem(pe.getMessage());
}
}
return modified;
}最后,这是加载的脚本之一:
(function() {
function process(name, input) {
if (input === null) return { result: null };
let tmp = input.trim();
if (tmp.length === 0) return { result: null };
// some logic here
return {
result: result !== '' ? result : null
};
}
function selfTest() {
}
return { process, selfTest };
})();这就是情况。当我运行这个应用程序并删除一个文件时,当第一个可编写脚本的字段在StackOverflowError行中被处理,并且JVM被终止(!)时,我会收到一个fnProcess.execute(data.SourceName, oldContent);。netbeans的脚本调试器显示,这发生在行let tmp = input.trim();中。当我删除trim()命令时,脚本将被执行,直到下一个函数调用字符串(如indexOf),但长度检查tmp.length === 0将正常执行(至少netbeans调试器会这样显示)。无论传递的字符串内容如何,都会出现问题,即使硬编码字符串也会在服务器环境中生成错误。
Uncaught exception exiting JVMCIEnv scope entered at c:\buildbot\worker\e\main\jdk\src\hotspot\share\jvmci\jvmciCompilerToVM.cpp:2386
Exception in thread "Thread-JobCenter": java.lang.StackOverflowError
java.lang.StackOverflowError
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.newStackOverflowError0(StackOverflowCheckImpl.java:363)
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.newStackOverflowError(StackOverflowCheckImpl.java:359)
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.throwNewStackOverflowError(StackOverflowCheckImpl.java:339)
at com.oracle.svm.core.graal.jdk.ArraycopySnippets.boundsCheck(ArraycopySnippets.java:117)
at com.oracle.svm.core.graal.jdk.ArraycopySnippets.doArraycopy(ArraycopySnippets.java:94)
at java.util.Arrays.copyOf(Arrays.java:3539)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:228)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:802)
at java.lang.StringBuilder.append(StringBuilder.java:242)
at com.oracle.svm.core.util.Utf8.utf8ToString(Utf8.java:144)
at com.oracle.svm.core.util.Utf8.utf8ToString(Utf8.java:187)
at com.oracle.svm.jni.functions.JNIFunctions.NewStringUTF(JNIFunctions.java:479)
at jdk.vm.ci.hotspot.CompilerToVM.getResolvedJavaType0(CompilerToVM.java)
at jdk.vm.ci.hotspot.CompilerToVM.getResolvedJavaType(CompilerToVM.java:674)
at jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.getHolder(HotSpotResolvedJavaMethodImpl.java:97)
at jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.fromMetaspace(HotSpotResolvedJavaMethodImpl.java:115)
at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl_2_0002efromMetaspace_00028J_00029Ljdk_vm_ci_hotspot_HotSpotResolvedJavaMethod_2(JNIJavaCallWrappers.java:0)
at org.graalvm.libgraal.jni.JNI$CallStaticObjectMethodA.call(JNI.java)
at org.graalvm.libgraal.jni.FromLibGraalCalls.callJObject(FromLibGraalCalls.java:153)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.HSTruffleCompilerRuntimeGen.callGetTruffleCallBoundaryMethods(HSTruffleCompilerRuntimeGen.java:181)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.HSTruffleCompilerRuntime.getTruffleCallBoundaryMethods(HSTruffleCompilerRuntime.java:356)
at org.graalvm.compiler.truffle.compiler.hotspot.HotSpotTruffleCompilerImpl.installTruffleCallBoundaryMethods(HotSpotTruffleCompilerImpl.java:216)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.TruffleToLibGraalEntryPoints.installTruffleCallBoundaryMethods(TruffleToLibGraalEntryPoints.java:305)
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (jvmciRuntime.cpp:1215), pid=15740, tid=10088
# fatal error: Fatal exception in JVMCI: Uncaught exception exiting JVMCIEnv scope entered at c:\buildbot\worker\e\main\jdk\src\hotspot\share\jvmci\jvmciCompilerToVM.cpp:2386
#
# JRE version: OpenJDK Runtime Environment GraalVM CE 21.1.0 (16.0.1+9) (build 16.0.1+9-jvmci-21.1-b05)
# Java VM: OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (16.0.1+9-jvmci-21.1-b05, mixed mode, sharing, tiered, jvmci, jvmci compiler, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Data\hs_err_pid15740.log
#
# If you would like to submit a bug report, please visit:
# https://github.com/oracle/graal/issues
#这是hs_err_pid15740.log的一部分
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j jdk.vm.ci.hotspot.CompilerToVM.translate(Ljava/lang/Object;)J+0 jdk.internal.vm.ci@16.0.1
j jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.translate(Ljava/lang/Object;)J+5 jdk.internal.vm.ci@16.0.1
j jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+40 java.base@16.0.1
j jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6 java.base@16.0.1
j java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+59 java.base@16.0.1
j org.graalvm.libgraal.LibGraal.translate(Ljava/lang/Object;)J+28 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.TruffleFromLibGraalEntryPoints.getTruffleCallBoundaryMethods(Ljava/lang/Object;)[J+122 jdk.internal.vm.compiler
v ~StubRoutines::call_stub
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.TruffleToLibGraalCalls.installTruffleCallBoundaryMethods(JJLorg/graalvm/compiler/truffle/common/CompilableTruffleAST;)V+0 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.LibGraalHotSpotTruffleCompiler.installTruffleCallBoundaryMethods(Lorg/graalvm/compiler/truffle/common/CompilableTruffleAST;)V+25 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.AbstractHotSpotTruffleRuntime.bypassedInstalledCode(Lorg/graalvm/compiler/truffle/runtime/OptimizedCallTarget;)V+14 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.interpreterCall()Z+11 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary([Ljava/lang/Object;)Ljava/lang/Object;+1 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke([Ljava/lang/Object;)Ljava/lang/Object;+2 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary([Ljava/lang/Object;)Ljava/lang/Object;+9 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke([Ljava/lang/Object;)Ljava/lang/Object;+2 jdk.internal.vm.compiler
// repeated for about 8000 rows...但是,当我使用与上面相同的脚本文件运行以下代码,并将相同的参数传递给javascript函数时,与服务器在文件删除时所做的一样,也不会抛出任何异常:
var ctx = Context.newBuilder("js").allowAllAccess(false).allowIO(true).build();
var js = java.nio.file.Files.readString(Path.of("scripts/0.js"));
var evaluated = ctx.eval("js", js);
var fn = evaluated.getMember("process");
var result = fn.execute("test", "some content ");我希望有人在巨大的短信交易中幸存下来,一直到这里然后告诉我我做错了什么.
发布于 2022-10-24 13:11:55
我可以通过将GraalVM升级到22.2版本来解决这个问题。遗憾的是,在这个版本中,javascript支持不再包含,必须与控制台一起添加。仍然不知道哪里出了问题(我几乎可以肯定,这个问题在上一个版本中并不存在)。
这不是我的功劳。但是,由于有大量的文本,人们可能只会在文本的末尾看到一个被接受的答案,而不会看到答案。
https://stackoverflow.com/questions/74111591
复制相似问题