【问题标题】:GraalVM - Using Polyglot Value without a contextGraalVM - 在没有上下文的情况下使用多语言值
【发布时间】:2018-08-03 09:10:31
【问题描述】:

我正在 Graal 之上编写一个应用程序,它将能够以不同的语言执行小脚本。

我正在尝试为我用来将 Context.eval() 调用(类型:值)的结果转换/处理为 Java 对象的类编写一些单元测试。我从文档中知道 Value 实例始终绑定到 Context,所以当我尝试编写类似这样的内容时:

@Test
public void NumericFloatTest() throws ScriptExecutionException {

    GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
    Float javaValue = (float) 43.25;
    Value numValue = Value.asValue(javaValue);
    LangProcessor.processResult(numValue);

    Object result = LangProcessor.processResult(numValue);

    assertThat(result.getClass()).isEqualTo(Float.class);
}

我收到以下错误:

java.lang.IllegalStateException: No current context is available. Make sure the Java method is invoked by a Graal guest language or a context is entered using Context.enter().

我想从概念上讲,没有相关的客户代码的“值”实例是没有意义的,所以我的问题是:

如何测试我的 GuestLanguageResultProcessor 类?我是否必须通过创建上下文来“膨胀”我的单元测试?

专家的附加问题:我正在使用这个类 (GuestLanguageResultProcessor) 从多语言值实例中提取 Java 值,以便我可以关闭上下文。换句话说,在我看来,在能够执行 Context.close() 之前,我需要调用 [value instance].asString() 或 .asWhatever() 以获取结果并能够在没有得到一个 IllegalStateException,正如它在 docs 中所说的那样。

我做得对吗?有没有更好的方法来处理获取结果并安全地关闭上下文?

谢谢!

【问题讨论】:

    标签: graalvm


    【解决方案1】:

    如何测试我的 GuestLanguageResultProcessor 类?我是否必须通过创建上下文来“膨胀”我的单元测试?

    我担心有点腹胀是必要的。我建议使用以下代码来进行测试。这也可以在测试基类中完成,以避免重复。

    Context context;
    
    @Before
    public void setup() {
        context = Context.create();
        context.enter();
    }
    
    @After
    public void setup() {
        context.leave();
        context.close();
    }
    
    @Test
    public void NumericFloatTest() throws ScriptExecutionException {
        GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
        Float javaValue = (float) 43.25;
        Value numValue = Value.asValue(javaValue);
        LangProcessor.processResult(numValue);
    
        Object result = LangProcessor.processResult(numValue);
    
        assertThat(result.getClass()).isEqualTo(Float.class);
    }
    

    我做得对吗?有没有更好的方法来处理获取结果并安全地关闭上下文?

    值实例可以绑定到客户语言对象,例如 JavaScript 对象,一旦它们的上下文关闭就无效。并非总是可以将客户语言对象转换为永久的 Java 表示。例如,多语言值可能指的是整个 JavaScript 对象图。

    如果可能,我建议在需要值时保持上下文打开,因为它不需要任何转换。

    如果这是不可能的,并且您只处理原语和数组,您可以尝试使用以下方法。您也可以尝试通过访问其成员将对象复制到 Java 领域。

    Object copyToJavaLand(Value value) {
        if (value.isBoolean()) {
            return value.asBoolean();
        } else if (value.isString()) {
            return value.asString();
        } else if (value.isNumber()) {
            return value.as(Number.class);
        } else if (value.isHostObject()) {
            return value.asHostObject();
        } else if (value.isProxyObject()) {
            return value.asProxyObject();
        } else if (value.hasArrayElements()) {
            Object[] array = new Object[(int) value.getArraySize()];
            for (int i = 0; i < array.length; i++) {
                array[i] = copyToJavaLand(value.getArrayElement(i));
            }
            return array;
        }
        throw new IllegalArgumentException("Cannot copy value " + value + ".");
    }
    

    请注意,这种方法并不总是安全的。例如,如果数组引用自身,则此方法会因堆栈溢出错误而崩溃。

    【讨论】:

    • 太棒了!感谢您的彻底回复。我有一个平行的问题,但我认为它值得单独发表。我已经把它贴在这里了:stackoverflow.com/questions/51707039/…谢谢你的帮助!
    猜你喜欢
    • 1970-01-01
    • 2019-02-25
    • 2021-06-03
    • 2021-03-20
    • 1970-01-01
    • 2012-07-01
    • 2013-05-19
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多