netbeans-html4j icon indicating copy to clipboard operation
netbeans-html4j copied to clipboard

Agent to change retention of `@JavaScriptBody` and `@JavaScriptResource`

Open jtulach opened this issue 11 months ago • 2 comments

To support use of HTML/Java API in GraalVM's native-image tool:

  • the @JavaScriptBody and @JavaScriptResource annotation need to be available in runtime
  • however they have RetentionType.CLASS
  • let's patch the bytecode then

It is necessary to change the bytecode of:

  • all classes using these annotations need to duplicate their usage into runtimeVisibleAnnotation class file attribute
  • all these annotations need to be patched to declare RetentionType.RUNTIME

With such changes we should be able to use the JVM agent of HTML/Java to make these annotation available at GraalVM's native image build time.

  • [x] Write a test to verify behavior of the -agentlib option
  • [x] Update documentation

jtulach avatar Jan 10 '25 16:01 jtulach

This PR properly implements the ideas discussed at https://github.com/oracle/graal/issues/8177#issuecomment-2376103806

jtulach avatar Jan 10 '25 17:01 jtulach

net.java.html.boot-2.0-SNAPSHOT.jar.gz JAR (after gzip -d) contains the Agent-Class attribute in its manifest:

/graalvm-21/bin/java \
    -javaagent:net.java.html.boot-2.0-SNAPSHOT.jar  \
    -cp net.java.html.boot-2.0-SNAPSHOT.jar \
    App.java

can be used to change the retention of the @JavaScriptBody & co. annotations as following App.java sample code demonstrates:

import net.java.html.js.JavaScriptBody;

class App {
  @JavaScriptBody(args={}, body="")
  public static native void hello();

  public static void main(String... args) throws Exception {
    var hello = App.class.getMethod("hello");
    System.err.println("method: " + hello);
    System.err.println("ann: " + hello.getAnnotation(JavaScriptBody.class));
  }
}

Executing the program should print: ann: [JavaScriptBody](method: @net.java.html.js.JavaScriptBody(wait4js=true, wait4java=true, javacall=false, keepAlive=true, args={}, body="")).

jtulach avatar Jan 11 '25 08:01 jtulach

Testing with Native Image

The primary goal of this change is to allow integration with GraalVM. Let's do a small test. Take GraalVM repository at release/graalvm-25.0 branch, in particular commit bb84380ba769081088ed5a95c2a4f3df9f1ac652:

graal/web-image$ mx build
graal/web-image$ graal/web-image$ mx web-image
Error: Please specify class (or <module>/<mainclass>) containing the main entry point method. (see --help)

With the mx web-image tool functioning. Let's create netbeans-html4j-test.sh file with the following content:

#!/bin/bash
set -e

mkdir -p hi

V=2.0-SNAPSHOT
CP=$1

if ! [ -e "$CP" ]; then
  echo Usage $0 '<path_to_net.java.html.boot.jar>'
  echo    - typical path may be: $HOME/.m2/repository/org/netbeans/html/net.java.html.boot/$V/net.java.html.boot-$V.jar
  exit 1
fi


cat >hi/Hi.java <<KONEC
class Hi {
  @net.java.html.js.JavaScriptBody(args="txt", body="""
    console.log(txt);
    return "...returning back from JavaScript...";
  """)
  private static native String hello(String txt);

  public static void main(String... args) {
    System.out.println("In JVM");
    var hi = hello("Hi from JavaScript");
    System.out.println(hi);
    System.out.println("Back in JVM");
  }
}
KONEC

javac -cp $CP hi/Hi.java -d hi

mx web-image -H:+UnlockExperimentalVMOptions  -o hi  -H:Path=hi \
 -H:+SILENT_COMPILE  -H:-ClosureCompiler  -H:+DumpPreClosure \
 -H:+VerificationPhases  -H:JSRuntime=Generic  -H:Class=Hi \
 -cp hi \
 -J-javaagent:$CP

node hi/hi.js

and then just launch it with net.java.html.boot-2.0-SNAPSHOT.jar.gz after uncompressing it with gzip -d:

graal/web-image$ ./netbeans-html4j-test.sh net.java.html.boot-2.0-SNAPSHOT.jar
======================
GraalVM Native Image: Generating 'hi' (executable)...
======================
...
In JVM
Hi from JavaScript
...returning back from JavaScript...
Back in JVM

Heuréka. CCing @pziegler, @toni-epple, @fniephaus - everything seems to be working. The next version of NetBeans/HTML API will easily generate the right code with mx web-image tool (with the help of -javaagent:net.java.html.boot.jar)!

jtulach avatar Jun 20 '25 17:06 jtulach