Browse Source

Add jni-config generation

This commit adds support generating graalvm `jni-config.json` file.

Configuration format for jni/reflection in graalvm is documented
to be exactly same so we can re-use facilities for reflection hints
which should be relatively clean for a user as also graalvm uses same
classes for both jni/reflection.

Closes gh-29007
pull/29130/head
Janne Valkealahti 2 years ago committed by Sébastien Deleuze
parent
commit
135f9070c5
  1. 11
      spring-core/src/main/java/org/springframework/aot/hint/RuntimeHints.java
  2. 9
      spring-core/src/main/java/org/springframework/aot/nativex/NativeConfigurationWriter.java
  3. 5
      spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java
  4. 18
      spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java

11
spring-core/src/main/java/org/springframework/aot/hint/RuntimeHints.java

@ -28,6 +28,7 @@ package org.springframework.aot.hint; @@ -28,6 +28,7 @@ package org.springframework.aot.hint;
* recorded as well.
*
* @author Stephane Nicoll
* @author Janne Valkealahti
* @since 6.0
*/
public class RuntimeHints {
@ -40,6 +41,8 @@ public class RuntimeHints { @@ -40,6 +41,8 @@ public class RuntimeHints {
private final ProxyHints proxies = new ProxyHints();
private final ReflectionHints jni = new ReflectionHints();
/**
* Provide access to reflection-based hints.
@ -73,4 +76,12 @@ public class RuntimeHints { @@ -73,4 +76,12 @@ public class RuntimeHints {
return this.proxies;
}
/**
* Provide access to jni-based hints.
* @return jni hints
*/
public ReflectionHints jni() {
return this.jni;
}
}

9
spring-core/src/main/java/org/springframework/aot/nativex/NativeConfigurationWriter.java

@ -29,6 +29,7 @@ import org.springframework.aot.hint.SerializationHints; @@ -29,6 +29,7 @@ import org.springframework.aot.hint.SerializationHints;
*
* @author Sebastien Deleuze
* @author Stephane Nicoll
* @author Janne Valkealahti
* @since 6.0
* @see <a href="https://www.graalvm.org/22.1/reference-manual/native-image/BuildConfiguration/">Native Image Build Configuration</a>
*/
@ -52,6 +53,9 @@ public abstract class NativeConfigurationWriter { @@ -52,6 +53,9 @@ public abstract class NativeConfigurationWriter {
hints.resources().resourceBundles().findAny().isPresent()) {
writeResourceHints(hints.resources());
}
if (hints.jni().typeHints().findAny().isPresent()) {
writeJniHints(hints.jni());
}
}
/**
@ -82,4 +86,9 @@ public abstract class NativeConfigurationWriter { @@ -82,4 +86,9 @@ public abstract class NativeConfigurationWriter {
ResourceHintsWriter.INSTANCE.write(writer, hints));
}
private void writeJniHints(ReflectionHints hints) {
writeTo("jni-config.json", writer ->
ReflectionHintsWriter.INSTANCE.write(writer, hints));
}
}

5
spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java

@ -34,12 +34,15 @@ import org.springframework.lang.Nullable; @@ -34,12 +34,15 @@ import org.springframework.lang.Nullable;
/**
* Write {@link ReflectionHints} to the JSON output expected by the GraalVM
* {@code native-image} compiler, typically named {@code reflect-config.json}.
* {@code native-image} compiler, typically named {@code reflect-config.json}
* or {@code jni-config.json}.
*
* @author Sebastien Deleuze
* @author Stephane Nicoll
* @author Janne Valkealahti
* @since 6.0
* @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/Reflection/">Reflection Use in Native Images</a>
* @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/JNI/">Java Native Interface (JNI) in Native Image</a>
* @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/BuildConfiguration/">Native Image Build Configuration</a>
*/
class ReflectionHintsWriter {

18
spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java

@ -49,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; @@ -49,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link FileNativeConfigurationWriter}.
*
* @author Sebastien Deleuze
* @author Janne Valkealahti
*/
public class FileNativeConfigurationWriterTests {
@ -149,6 +150,23 @@ public class FileNativeConfigurationWriterTests { @@ -149,6 +150,23 @@ public class FileNativeConfigurationWriterTests {
]""", "reflect-config.json");
}
@Test
void jniConfig() throws IOException, JSONException {
// same format as reflection so just test basic file generation
FileNativeConfigurationWriter generator = new FileNativeConfigurationWriter(tempDir);
RuntimeHints hints = new RuntimeHints();
ReflectionHints jniHints = hints.jni();
jniHints.registerType(StringDecoder.class, builder -> builder.onReachableType(String.class));
generator.write(hints);
assertEquals("""
[
{
"name": "org.springframework.core.codec.StringDecoder",
"condition": { "typeReachable": "java.lang.String" }
}
]""", "jni-config.json");
}
@Test
void resourceConfig() throws IOException, JSONException {
FileNativeConfigurationWriter generator = new FileNativeConfigurationWriter(tempDir);

Loading…
Cancel
Save