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

Truffle Espresso and Truffle JS behave differently under Hotspot #5850

Closed
linghengqian opened this issue Jan 30, 2023 · 5 comments
Closed

Truffle Espresso and Truffle JS behave differently under Hotspot #5850

linghengqian opened this issue Jan 30, 2023 · 5 comments
Assignees

Comments

@linghengqian
Copy link

linghengqian commented Jan 30, 2023

Describe GraalVM and your environment :

  • GraalVM version or commit id if built from source: [e.g. 19.3] 22.3.1
  • CE or EE: [e.g.: CE] CE
  • JDK version: [e.g.: JDK8] JDK17
  • OS and OS Version: [e.g.: macOS Catalina] Ubuntu 22.04
  • Architecture: [e.g.: amd64] amd64
  • The output of java -Xinternalversion:
OpenJDK 64-Bit Server VM (17.0.6+10-LTS) for linux-amd64 JRE (17.0.6+10-LTS), built on Jan 18 2023 19:58:28 by "MicrosoftCorporation" with gcc 11.3.0

Have you verified this issue still happens when using the latest snapshot?
You can find snapshot builds here: https://github.com/graalvm/graalvm-ce-dev-builds/releases

  • I haven't verified, but I feel like this involves something unfinished in espresso.

Describe the issue
A clear and concise description of the issue.

  • Truffle Espresso and Truffle JS behave differently under Hotspot. In my understanding, https://www.graalvm.org/22.3/reference-manual/java-on-truffle/faq/#does-java-running-on-truffle-run-on-hotspot-too means, both Truffle Espresso and Truffle JS should be able to install dependencies through package managers such as Maven or Gradle. But it seems only Truffle JS can do that.
  • I've provided a Git below that works fine when running Truffle JS under Microsoft OpenJDK, but when running Truffle Espresso, Espresso fails to initialize properly. I'm not sure if this is the normal way to use Espresso with Hotspot.

Code snippet or code repository that reproduces the issue

package com.lingh;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.junit.jupiter.api.Test;

public class TruffleTest {
    @Test
    void testJs() {
        try (Context context = Context.create()) {
            Value result = context.eval("js", "40+2");
            assert result.asInt() == 42;
        }
    }
    @Test
    void testEspresso() {
        try (Context polyglot = Context.newBuilder().allowNativeAccess(true).build()) {
            Value java_lang_Math = polyglot.getBindings("java").getMember(Math.class.getName());
            double sqrt2 = java_lang_Math.invokeMember("sqrt", 2).asDouble();
            double pi = java_lang_Math.getMember("PI").asDouble();
            assert sqrt2 == 1.4142135623730951;
            assert pi == 3.141592653589793;
        }
    }
}

Steps to reproduce the issue
Please include both build steps as well as run steps

  1. Step one [e.g.: git clone --depth 1 https://git.myrepo.com/projectone ]
  1. Step two [e.g.: mvn clean package]
  • The steps to reproduce under Ubuntu 22.04 are as follows.
sudo apt install unzip zip curl sed -y
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 17.0.6-ms
sdk use java 17.0.6-ms

git clone [email protected]:linghengqian/hotspot-espresso-js-test.git
cd ./hotspot-espresso-js-test/
./gradlew clean test

Expected behavior
A clear and concise description of what you expected to happen.

  • ./gradlew clean test should be fine.

Additional context
Add any other context about the problem here. Specially important are stack traces or log output. Feel free to link to gists or to screenshots if necesary

Details
java.lang.IllegalArgumentException: A language with id 'java' is not installed. Installed languages are: [js].
	at com.oracle.truffle.polyglot.PolyglotEngineException.illegalArgument(PolyglotEngineException.java:131)
	at com.oracle.truffle.polyglot.PolyglotEngineImpl.throwNotInstalled(PolyglotEngineImpl.java:1109)
	at com.oracle.truffle.polyglot.PolyglotEngineImpl.requirePublicLanguage(PolyglotEngineImpl.java:1116)
	at com.oracle.truffle.polyglot.PolyglotContextImpl.requirePublicLanguage(PolyglotContextImpl.java:1491)
	at com.oracle.truffle.polyglot.PolyglotContextImpl.lookupLanguageContext(PolyglotContextImpl.java:1453)
	at com.oracle.truffle.polyglot.PolyglotContextImpl.getBindings(PolyglotContextImpl.java:1201)
	at com.oracle.truffle.polyglot.PolyglotContextDispatch.getBindings(PolyglotContextDispatch.java:98)
	at org.graalvm.polyglot.Context.getBindings(Context.java:560)
	at com.lingh.TruffleTest.testEspresso(TruffleTest.java:18)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
@oubidar-Abderrahim
Copy link
Member

Hi, Thank you for reaching out about this issue.

Do you have Espresso installed? you can verify this by running gu list
image

If you don't, please install it using gu install espresso

@linghengqian
Copy link
Author

  • @oubidar-Abderrahim Hi, I mentioned in the issue that I'm trying to execute this unit test in a JVM other than GraalVM CE, so there is no system environment variable for gu. I noticed that most of the Truffle languages ​​can be directly used in OpenJDK like Microsoft OpenJDK through Maven dependencies without GraalVM CE. Can't do this for Truffle Espresso, is there any background on this?

@mukel
Copy link
Member

mukel commented Feb 6, 2023

We do not publish (full) Espresso on Maven, only some guest APIs as .jars.
It is possible to run Espresso on any JVM, but the setup is rather cumbersome.

Running Espresso in other JVMs will run in interpreter only mode, performance will be substantially lower. If that is not an issue then:

Download the latest GraalVM matching the Java version of your MS JVM:
Copy $GRAALVM_HOME/languages, note that this folder should include at least java, nfi, nfi-libffi folders, into $YOUR_PROJECT/languages and $GRAALVM_HOME/lib/trufflenfi.so into $YOUR_PROJECT/lib/trufflenfi.so.

Here's the modified build.gradle:

plugins {
    id 'java'
}

group 'com.lingh'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
    implementation 'org.graalvm.js:js:22.3.1'

    // These are guest APIs, can only be used within Espresso.
    // implementation 'org.graalvm.espresso:polyglot:22.3.1'
    // implementation 'org.graalvm.espresso:hotswap:22.3.1'

    // Some deps are missing on 22.3.1, so we add them manually, see below
    // implementation 'org.graalvm.truffle:truffle-nfi:22.3.1'
    // implementation 'org.graalvm.truffle:truffle-nfi-libffi:22.3.1'

    implementation files('languages/java/espresso.jar')
    implementation files('languages/nfi/truffle-nfi.jar')
    implementation files('languages/nfi-libffi/truffle-nfi-libffi.jar')
}

test {
    useJUnitPlatform()
    systemProperty "org.graalvm.language.java.home", "languages/java"

    File nfiLibrary = file('lib/libtrufflenfi.so')
    systemProperty "truffle.nfi.library", nfiLibrary.absolutePath
}

To create an Espresso context, you'll need some extra options:

    @Test
    void testEspresso() {
        try (Context polyglot = Context.newBuilder()
              .allowNativeAccess(true)
              .allowExperimentalOptions(true)
              .option("java.JavaHome", System.getProperty("java.home")) // guest Java home, can be any 8/11/17 Java Home.
              .option("java.JVMLibraryPath", "languages/java/lib/") // required, we need to know where to look for Espresso's libjvm.so 
              .build()) {
            Value java_lang_Math = polyglot.getBindings("java").getMember(Math.class.getName());
            double sqrt2 = java_lang_Math.invokeMember("sqrt", 2).asDouble();
            double pi = java_lang_Math.getMember("PI").asDouble();
            System.err.println("PI=" + pi);
            System.err.println("sqrt2=" + sqrt2);
        }
    }

And that's it. Please note that this franken-JVM is not recommended, running Espresso on GraalVM will give you, at least, one order of magnitude better performance.

@mukel
Copy link
Member

mukel commented Feb 6, 2023

@linghengqian if you have a convincing use case, please file a feature request to run Espresso standalone from Maven.

@linghengqian
Copy link
Author

@mukel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants