diff --git a/.github/workflows/native-image-reflection-example.yml b/.github/workflows/native-image-reflection-example.yml deleted file mode 100644 index ab3559da3..000000000 --- a/.github/workflows/native-image-reflection-example.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: native-image-reflection-example -on: - push: - paths: - - 'native-image-reflection-example/**' - - '.github/workflows/native-image-reflection-example.yml' - pull_request: - paths: - - 'native-image-reflection-example/**' - - '.github/workflows/native-image-reflection-example.yml' - schedule: - - cron: "0 0 1 * *" # run every month - workflow_dispatch: -permissions: - contents: read -jobs: - run: - name: Run 'native-image-reflection-example' - runs-on: ubuntu-latest - timeout-minutes: 15 - strategy: - matrix: - java-version: ['21', 'dev'] - steps: - - uses: actions/checkout@v4 - - uses: graalvm/setup-graalvm@v1 - with: - java-version: ${{ matrix.java-version }} - distribution: 'graalvm' - github-token: ${{ secrets.GITHUB_TOKEN }} - native-image-job-reports: 'true' - - name: Run 'native-image-reflection-example' - run: | - cd native-image-reflection-example - javac ReflectionExample.java - mkdir -p META-INF/native-image - java -agentlib:native-image-agent=config-output-dir=META-INF/native-image ReflectionExample StringReverser reverse "hello" - java -agentlib:native-image-agent=config-merge-dir=META-INF/native-image ReflectionExample StringCapitalizer capitalize "hello" - native-image ReflectionExample - ./reflectionexample StringReverser reverse "hello" - ./reflectionexample StringCapitalizer capitalize "hello" \ No newline at end of file diff --git a/.github/workflows/native-image-access-environment-variables.yml b/.github/workflows/native-image/access-environment-variables.yml similarity index 88% rename from .github/workflows/native-image-access-environment-variables.yml rename to .github/workflows/native-image/access-environment-variables.yml index 852d94302..f951b46e5 100644 --- a/.github/workflows/native-image-access-environment-variables.yml +++ b/.github/workflows/native-image/access-environment-variables.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/access-environment-variables/**' - - '.github/workflows/native-image-access-environment-variables.yml' + - '.github/workflows/native-image/access-environment-variables.yml' pull_request: paths: - 'native-image/access-environment-variables/**' - - '.github/workflows/native-image-access-environment-variables.yml' + - '.github/workflows/native-image/access-environment-variables.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image-add-jfr-support.yml b/.github/workflows/native-image/add-jfr.yml similarity index 61% rename from .github/workflows/native-image-add-jfr-support.yml rename to .github/workflows/native-image/add-jfr.yml index d0bad22a7..2b80fc799 100644 --- a/.github/workflows/native-image-add-jfr-support.yml +++ b/.github/workflows/native-image/add-jfr.yml @@ -1,13 +1,13 @@ -name: native-image/add-jfr-support +name: native-image/add-jfr on: push: paths: - - 'native-image/add-jfr-support/**' - - '.github/workflows/native-image-add-jfr-support.yml' + - 'native-image/add-jfr/**' + - '.github/workflows/native-image/add-jfr.yml' pull_request: paths: - - 'native-image/add-jfr-support/**' - - '.github/workflows/native-image-add-jfr-support.yml' + - 'native-image/add-jfr/**' + - '.github/workflows/native-image/add-jfr.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: @@ -15,7 +15,7 @@ permissions: contents: read jobs: run: - name: Run 'native-image/add-jfr-support' + name: Run 'native-image/add-jfr' runs-on: ubuntu-latest timeout-minutes: 15 strategy: @@ -29,7 +29,7 @@ jobs: distribution: 'graalvm' github-token: ${{ secrets.GITHUB_TOKEN }} native-image-job-reports: 'true' - - name: Run 'native-image/add-jfr-support' + - name: Run 'native-image/add-jfr' run: | - cd native-image/add-jfr-support + cd native-image/add-jfr ./run.sh diff --git a/.github/workflows/native-image-add-jmx-support.yml b/.github/workflows/native-image/add-jmx.yml similarity index 75% rename from .github/workflows/native-image-add-jmx-support.yml rename to .github/workflows/native-image/add-jmx.yml index d54f0d1ee..0e26eda0f 100644 --- a/.github/workflows/native-image-add-jmx-support.yml +++ b/.github/workflows/native-image/add-jmx.yml @@ -1,13 +1,13 @@ -name: native-image/add-jmx-support +name: native-image/add-jmx on: push: paths: - - 'native-image/add-jmx-support/**' - - '.github/workflows/native-image-add-jmx-support.yml' + - 'native-image/add-jmx/**' + - '.github/workflows/native-image/add-jmx.yml' pull_request: paths: - - 'native-image/add-jmx-support/**' - - '.github/workflows/native-image-add-jmx-support.yml' + - 'native-image/add-jmx/**' + - '.github/workflows/native-image/add-jmx.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: @@ -15,7 +15,7 @@ permissions: contents: read jobs: run: - name: Run 'native-image/add-jmx-support' + name: Run 'native-image/add-jmx' runs-on: ubuntu-latest timeout-minutes: 15 strategy: @@ -29,9 +29,9 @@ jobs: distribution: 'graalvm' github-token: ${{ secrets.GITHUB_TOKEN }} native-image-job-reports: 'true' - - name: Run 'native-image/add-jmx-support' + - name: Run 'native-image/add-jmx' run: | - cd native-image/add-jmx-support + cd native-image/add-jmx wget -q https://github.com/jiaqi/jmxterm/releases/download/v1.0.2/jmxterm-1.0.2-uber.jar javac SimpleJmx.java native-image -Ob --enable-monitoring=jmxserver,jmxclient,jvmstat -H:DynamicProxyConfigurationFiles=proxy-config.json SimpleJmx diff --git a/.github/workflows/native-image-add-logging.yml b/.github/workflows/native-image/add-logging.yml similarity index 87% rename from .github/workflows/native-image-add-logging.yml rename to .github/workflows/native-image/add-logging.yml index c9890849c..7c1cc0c5a 100644 --- a/.github/workflows/native-image-add-logging.yml +++ b/.github/workflows/native-image/add-logging.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/add-logging/**' - - '.github/workflows/native-image-add-logging.yml' + - '.github/workflows/native-image/add-logging.yml' pull_request: paths: - 'native-image/add-logging/**' - - '.github/workflows/native-image-add-logging.yml' + - '.github/workflows/native-image/add-logging.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image-build-from-jar.yml b/.github/workflows/native-image/build-from-jar.yml similarity index 87% rename from .github/workflows/native-image-build-from-jar.yml rename to .github/workflows/native-image/build-from-jar.yml index a52bdeff7..86b53f526 100644 --- a/.github/workflows/native-image-build-from-jar.yml +++ b/.github/workflows/native-image/build-from-jar.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/build-from-jar/**' - - '.github/workflows/native-image-build-from-jar.yml' + - '.github/workflows/native-image/build-from-jar.yml' pull_request: paths: - 'native-image/build-from-jar/**' - - '.github/workflows/native-image-build-from-jar.yml' + - '.github/workflows/native-image/build-from-jar.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image-build-java-modules.yml b/.github/workflows/native-image/build-java-modules.yml similarity index 87% rename from .github/workflows/native-image-build-java-modules.yml rename to .github/workflows/native-image/build-java-modules.yml index da03e922b..2654b23ca 100644 --- a/.github/workflows/native-image-build-java-modules.yml +++ b/.github/workflows/native-image/build-java-modules.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/build-java-modules/**' - - '.github/workflows/native-image-build-java-modules.yml' + - '.github/workflows/native-image/build-java-modules.yml' pull_request: paths: - 'native-image/build-java-modules/**' - - '.github/workflows/native-image-build-java-modules.yml' + - '.github/workflows/native-image-build/java-modules.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image-build-shared-library.yml b/.github/workflows/native-image/build-shared-library.yml similarity index 87% rename from .github/workflows/native-image-build-shared-library.yml rename to .github/workflows/native-image/build-shared-library.yml index 8505852e8..b3d13ddca 100644 --- a/.github/workflows/native-image-build-shared-library.yml +++ b/.github/workflows/native-image/build-shared-library.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/build-shared-library/**' - - '.github/workflows/native-image-build-shared-library.yml' + - '.github/workflows/native-image/build-shared-library.yml' pull_request: paths: - 'native-image/build-shared-library/**' - - '.github/workflows/native-image-build-shared-library.yml' + - '.github/workflows/native-image/build-shared-library.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image/build-static-images.yml b/.github/workflows/native-image/build-static-images.yml new file mode 100644 index 000000000..3e5ae7583 --- /dev/null +++ b/.github/workflows/native-image/build-static-images.yml @@ -0,0 +1,53 @@ +name: native-image/build-static-images +on: + push: + paths: + - 'native-image/build-static-images/**' + - '.github/workflows/native-image/build-static-images.yml' + pull_request: + paths: + - 'native-image/build-static-images/**' + - '.github/workflows/native-image/build-static-images.yml' + schedule: + - cron: "0 0 1 * *" # run every month + workflow_dispatch: +permissions: + contents: read +jobs: + run-static: + name: Run fully static + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + matrix: + java-version: ['21', '24-ea'] + steps: + - uses: actions/checkout@v4 + - uses: graalvm/setup-graalvm@v1 + with: + java-version: ${{ matrix.java-version }} + native-image-musl: 'true' + github-token: ${{ secrets.GITHUB_TOKEN }} + native-image-job-reports: 'true' + - name: Run fully static + run: | + cd native-image/build-static-images + javac EnvMap.java + native-image --static --libc=musl EnvMap -o static-envmap + run-mostly-static: + name: Run mostly-static + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: graalvm/setup-graalvm@v1 + with: + java-version: '24-ea' + distribution: 'graalvm' + github-token: ${{ secrets.GITHUB_TOKEN }} + native-image-job-reports: 'true' + - name: Run mostly-static + run: | + cd native-image/build-static-images + javac EnvMap.java + native-image -Ob --static-nolibc EnvMap -o mostly-static-envmap \ No newline at end of file diff --git a/.github/workflows/native-image-build-with-js-embedded.yml b/.github/workflows/native-image/build-with-js-embedded.yml similarity index 86% rename from .github/workflows/native-image-build-with-js-embedded.yml rename to .github/workflows/native-image/build-with-js-embedded.yml index ecef55ea6..5f8f37425 100644 --- a/.github/workflows/native-image-build-with-js-embedded.yml +++ b/.github/workflows/native-image/build-with-js-embedded.yml @@ -3,11 +3,11 @@ on: push: paths: - 'native-image/build-with-js-embedded/**' - - '.github/workflows/native-image-build-with-js-embedded.yml' + - '.github/workflows/native-image/build-with-js-embedded.yml' pull_request: paths: - 'native-image/build-with-js-embedded/**' - - '.github/workflows/native-image-build-with-js-embedded.yml' + - '.github/workflows/native-image/build-with-js-embedded.yml' schedule: - cron: "0 0 1 * *" # run every month workflow_dispatch: diff --git a/.github/workflows/native-image/configure-with-tracing-agent.yml b/.github/workflows/native-image/configure-with-tracing-agent.yml new file mode 100644 index 000000000..9dc74fa09 --- /dev/null +++ b/.github/workflows/native-image/configure-with-tracing-agent.yml @@ -0,0 +1,35 @@ +name: native-image/configure-with-tracing-agent +on: + push: + paths: + - 'native-image/configure-with-tracing-agent/**' + - '.github/workflows/native-image/configure-with-tracing-agent.yml' + pull_request: + paths: + - 'native-image/configure-with-tracing-agent/**' + - '.github/workflows/native-image/configure-with-tracing-agent.yml' + schedule: + - cron: "0 0 1 * *" # run every month + workflow_dispatch: +permissions: + contents: read +jobs: + run: + name: Run 'native-image/configure-with-tracing-agent + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + matrix: + java-version: ['21', '24-ea'] + steps: + - uses: actions/checkout@v4 + - uses: graalvm/setup-graalvm@v1 + with: + java-version: ${{ matrix.java-version }} + distribution: 'graalvm' + github-token: ${{ secrets.GITHUB_TOKEN }} + native-image-job-reports: 'true' + - name: Run 'native-image/configure-with-tracing-agent' + run: | + cd native-image/configure-with-tracing-agent + ./run.sh \ No newline at end of file diff --git a/native-image-reflection-example/README.md b/native-image-reflection-example/README.md deleted file mode 100644 index 15cb5d6bc..000000000 --- a/native-image-reflection-example/README.md +++ /dev/null @@ -1,144 +0,0 @@ -# Native Image Support for Java Reflection - -[Reflection](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/package-summary.html) is a feature of the Java programming language that enables a running Java program to examine and modify attributes of its classes, interfaces, fields, and methods. - -GraalVM Native Image provides partial support for reflection. It uses static analysis to detect the elements of your application that are accessed using the [Java Reflection API](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/package-summary.html). However, because the analysis is static, it cannot always completely predict all usages of the API when the program runs. Undetected usages must be provided to the `native-image` tool in the form of metadata (precomputed in code or as JSON configuration files). - -The following application demonstrates the use of Java reflection and how to provide metadata for `native-image` using a JSON configuration file. - -## Preparation - -1. Download and install the latest GraalVM JDK using [SDKMAN!](https://sdkman.io/). - ```bash - sdk install java 21.0.1-graal - ``` - -2. Download or clone the repository and navigate into the `native-image-reflection-example` directory: - ```bash - git clone https://github.com/graalvm/graalvm-demos - ``` - ```bash - cd graalvm-demos/native-image-reflection-example - ``` - -## Example with No Configuration - -1. Compile the application and invoke the `StringReverser()` and `StringCapitalizer()` methods: - ```shell - $JAVA_HOME/bin/javac ReflectionExample.java - ``` - ```shell - $JAVA_HOME/bin/java ReflectionExample StringReverser reverse "hello" - ``` - ```shell - $JAVA_HOME/bin/java ReflectionExample StringCapitalizer capitalize "hello" - ``` - - The output of each command should be `"olleh"` and `"HELLO"`, respectively. (An exception is thrown if you provide any other string to identify the class or method.) - -2. Use the `native-image` utility to create a native executable as follows: - ```shell - $JAVA_HOME/bin/native-image --no-fallback ReflectionExample - ``` - > NOTE: The `--no-fallback` option to `native-image` causes the utility to fail if it can not create an executable file. - -3. Run the resulting native executable, using the following command: - ```bash - ./reflectionexample StringReverser reverse "hello" - ``` - You will see a `ClassNotFoundException` exception, similar to: - ```shell - Exception in thread "main" java.lang.ClassNotFoundException: StringReverser - at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:122) - at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:86) - at java.base@21/java.lang.Class.forName(DynamicHub.java:1346) - at java.base@21/java.lang.Class.forName(DynamicHub.java:1309) - at java.base@21/java.lang.Class.forName(DynamicHub.java:1302) - at ReflectionExample.main(ReflectionExample.java:68) - at java.base@21/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH) - ``` - - This shows that, from its static analysis, the `native-image` tool was unable to determine that class `StringReverser` is used by the application and therefore did not include it in the native executable. - -## Example with Configuration - -To build a native executable containing references to the classes and methods that are accessed via reflection, provide the `native-image` utility with a configuration file that specifies the classes and corresponding methods. For more information about configuration files, see [Reflection Use in Native Images](https://www.graalvm.org/latest/reference-manual/native-image/dynamic-features/Reflection/). You can create this file by hand, but a more convenient approach is to generate it using the tracing agent. The agent writes the configuration for you automatically when you run your application (for more information, see [Assisted Configuration with Tracing Agent](https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/#tracing-agent)). - -The following steps demonstrate how to use the tracing agent tool, and its output, to create a native executable that relies on reflection. - -1. Create a directory `META-INF/native-image` in the working directory: - ```shell - mkdir -p META-INF/native-image - ``` - -2. Run the application with the tracing agent enabled, as follows: - ```shell - $JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=META-INF/native-image ReflectionExample StringReverser reverse "hello" - ``` - This command creates a file named _reflection-config.json_ containing the name of the class `StringReverser` and its `reverse()` method. - ```json - [ - { - "name":"StringReverser", - "methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }] - } - ] - ``` - -3. Build a native executable: - ```shell - $JAVA_HOME/bin/native-image ReflectionExample - ``` - - The `native-image` tool automatically uses configuration files in the _META-INF/native-image_ directory. - It is recommended that the _META-INF/native-image_ directory is on the class path, either via a JAR file or using the `-cp` flag. (This avoids confusion for IDE users where a directory structure is defined by the IDE itself.) - -4. Test your executable: - ```shell - ./reflectionexample StringReverser reverse "hello" - ``` - The output of command should be `"olleh"` - - ```shell - ./reflectionexample StringCapitalizer capitalize "hello" - ``` - - You will see a `ClassNotFoundException` exception again. - - Neither the tracing agent nor the `native-image` tool can ensure that the configuration file is complete. - The agent observes and records which program elements are accessed using reflection when you run the program. In this case, the `native-image` tool has not been configured to include references to class `StringCapitalizer`. - -5. Update the configuration to include class `StringCapitalizer`. You can manually edit the _reflection-config.json_ file or re-run the tracing agent to update the existing configuration file using the `config-merge-dir` option, as follows: - ```shell - $JAVA_HOME/bin/java -agentlib:native-image-agent=config-merge-dir=META-INF/native-image ReflectionExample StringCapitalizer capitalize "hello" - ``` - - This command updates the _reflection-config.json_ file to include the name of the class `StringCapitalizer` and its `capitalize()` method. - ```json - [ - { - "name":"StringCapitalizer", - "methods":[{"name":"capitalize","parameterTypes":["java.lang.String"] }] - }, - { - "name":"StringReverser", - "methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }] - } - ] - ``` - -6. Rebuild a native executable and run the resulting executable: - ```shell - $JAVA_HOME/bin/native-image ReflectionExample - ``` - ```shell - ./reflectionexample StringCapitalizer capitalize "hello" - ``` - - The application should now work as intended. - -### Related Documentation - -* [Reachability Metadata: Reflection](https://www.graalvm.org/latest/reference-manual/native-image/metadata/) -* [Assisted Configuration with Tracing Agent](https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/#tracing-agent) -* [java.lang.reflect Javadoc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/package-summary.html) \ No newline at end of file diff --git a/native-image/add-jfr-support/.gitignore b/native-image/add-jfr/.gitignore similarity index 100% rename from native-image/add-jfr-support/.gitignore rename to native-image/add-jfr/.gitignore diff --git a/native-image/add-jfr-support/JFRDemo.java b/native-image/add-jfr/JFRDemo.java similarity index 100% rename from native-image/add-jfr-support/JFRDemo.java rename to native-image/add-jfr/JFRDemo.java diff --git a/native-image/add-jfr-support/README.md b/native-image/add-jfr/README.md similarity index 100% rename from native-image/add-jfr-support/README.md rename to native-image/add-jfr/README.md diff --git a/native-image/add-jfr-support/run.sh b/native-image/add-jfr/run.sh similarity index 100% rename from native-image/add-jfr-support/run.sh rename to native-image/add-jfr/run.sh diff --git a/native-image/add-jmx-support/.gitignore b/native-image/add-jmx/.gitignore similarity index 100% rename from native-image/add-jmx-support/.gitignore rename to native-image/add-jmx/.gitignore diff --git a/native-image/add-jmx-support/README.md b/native-image/add-jmx/README.md similarity index 100% rename from native-image/add-jmx-support/README.md rename to native-image/add-jmx/README.md diff --git a/native-image/add-jmx-support/SimpleJmx.java b/native-image/add-jmx/SimpleJmx.java similarity index 100% rename from native-image/add-jmx-support/SimpleJmx.java rename to native-image/add-jmx/SimpleJmx.java diff --git a/native-image/add-jmx-support/proxy-config.json b/native-image/add-jmx/proxy-config.json similarity index 100% rename from native-image/add-jmx-support/proxy-config.json rename to native-image/add-jmx/proxy-config.json diff --git a/native-image/add-jmx-support/run.sh b/native-image/add-jmx/run.sh similarity index 100% rename from native-image/add-jmx-support/run.sh rename to native-image/add-jmx/run.sh diff --git a/native-image-reflection-example/.gitignore b/native-image/configure-with-tracing-agent/.gitignore similarity index 100% rename from native-image-reflection-example/.gitignore rename to native-image/configure-with-tracing-agent/.gitignore diff --git a/native-image/configure-with-tracing-agent/README.md b/native-image/configure-with-tracing-agent/README.md new file mode 100644 index 000000000..8020b1c5a --- /dev/null +++ b/native-image/configure-with-tracing-agent/README.md @@ -0,0 +1,3 @@ +# Configure Native Image with the Tracing Agent + +You can find the steps to run this demo on [the website](https://www.graalvm.org/latest/reference-manual/native-image/guides/configure-with-tracing-agent/). \ No newline at end of file diff --git a/native-image-reflection-example/ReflectionExample.java b/native-image/configure-with-tracing-agent/ReflectionExample.java similarity index 100% rename from native-image-reflection-example/ReflectionExample.java rename to native-image/configure-with-tracing-agent/ReflectionExample.java diff --git a/native-image/configure-with-tracing-agent/run.sh b/native-image/configure-with-tracing-agent/run.sh new file mode 100755 index 000000000..360fbedac --- /dev/null +++ b/native-image/configure-with-tracing-agent/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -ex + +javac ReflectionExample.java +java ReflectionExample StringReverser reverse "hello" +java ReflectionExample StringCapitalizer capitalize "hello" +native-image -Ob ReflectionExample +./reflectionexample StringReverser reverse "hello" +./reflectionexample StringCapitalizer capitalize "hello" +mkdir -p META-INF/native-image +java -agentlib:native-image-agent=config-output-dir=META-INF/native-image ReflectionExample StringReverser reverse "hello" +java -agentlib:native-image-agent=config-merge-dir=META-INF/native-image ReflectionExample StringCapitalizer capitalize "hello" +native-image -Ob ReflectionExample +./reflectionexample StringReverser reverse "hello" +./reflectionexample StringCapitalizer capitalize "hello" \ No newline at end of file