Skip to content

Commit ba57ebe

Browse files
committed
Add graalvm feature to support System.Logger and slf4j-jdk-platform-logging
This could well move into avaje-simple-logger rather than be this separate module. Just not 100% sure if that is the right thing to do yet, so putting it here in this separate module until we are sure.
1 parent 73951a1 commit ba57ebe

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

graalvm-feature/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# avaje-simple-logger-graalvm-feature
2+
3+
When we want to use `slf4j-jdk-platform-logging` with graalvm native-image like:
4+
```xml
5+
<dependency>
6+
<groupId>org.slf4j</groupId>
7+
<artifactId>slf4j-jdk-platform-logging</artifactId>
8+
<version>2.0.17</version>
9+
</dependency>
10+
```
11+
we can have the issue that native-image wants to initialise the JDK logging at *BUILD* time.
12+
So this means that if we want to use `avaje-simple-logger`, we also need to initialise it's
13+
classes at build time as well - this is what the `avaje-simple-logger-graalvm-feature` does.
14+
15+
```xml
16+
<dependency> <!-- redirect System.Logger to slf4j -->
17+
<groupId>org.slf4j</groupId>
18+
<artifactId>slf4j-jdk-platform-logging</artifactId>
19+
<version>2.0.17</version>
20+
</dependency>
21+
22+
<dependency> <!-- logger implementation for sl4j-->
23+
<groupId>io.avaje</groupId>
24+
<artifactId>avaje-simple-logger</artifactId>
25+
<version>1.0</version>
26+
</dependency>
27+
28+
<dependency> <!-- with graalvm, use build time initialisation -->
29+
<groupId>io.avaje</groupId>
30+
<artifactId>avaje-simple-logger-graalvm-feature</artifactId>
31+
<version>0.1</version>
32+
</dependency>
33+
34+
```
35+
36+
## How to use
37+
38+
Add the dependency below. It will automatically register with graalvm native-image
39+
compilation to use the `io.avaje.simplelogger.graalvm.BuildInitialization` feature.
40+
41+
```xml
42+
<dependency> <!-- with graalvm, use build time initialisation -->
43+
<groupId>io.avaje</groupId>
44+
<artifactId>avaje-simple-logger-graalvm-feature</artifactId>
45+
<version>0.1</version>
46+
</dependency>
47+
48+
```
49+
50+
That's it.
51+
52+
Anything using JDK System.Logger, should now be logged using avaje-simple-logger.

graalvm-feature/pom.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>io.avaje</groupId>
8+
<artifactId>avaje-simple-logger-parent</artifactId>
9+
<version>1.0</version>
10+
</parent>
11+
12+
<artifactId>avaje-simple-logger-graalvm-feature</artifactId>
13+
<name>avaje-simple-logger-graalvm-feature</name>
14+
<version>0.1</version>
15+
16+
<properties>
17+
<maven.compiler.release>21</maven.compiler.release>
18+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.graalvm.nativeimage</groupId>
24+
<artifactId>svm</artifactId>
25+
<version>25.0.1</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.avaje.simplelogger.graalvm;
2+
3+
4+
import org.graalvm.nativeimage.hosted.Feature;
5+
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
6+
7+
/**
8+
* GraalVM Native Image build Feature that initialises Simple Logger classes at Build time.
9+
* <p>
10+
* Use this when using slf4j-jdk-platform-logging to redirect System.Logger to slf4j. This
11+
* is needed as GraalVM by default initialised JDK logging at build time. Adding this
12+
* feature supports redirecting System.Logger to avaje simple logger by also initialising
13+
* the avaje simple logger classes at build time.
14+
* </p>
15+
*/
16+
public class BuildInitialization implements Feature {
17+
18+
@Override
19+
public void beforeAnalysis(BeforeAnalysisAccess access) {
20+
// Register a specific class to be initialized at runtime
21+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$PatternFilter"));
22+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$ReflectiveInvocation"));
23+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$SpringFilter"));
24+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$Generated"));
25+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$Group"));
26+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.FilterBuilder$JDKInternals"));
27+
28+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.StackElementFilter"));
29+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.AbbreviatorByLength"));
30+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.AbbreviatorCaching"));
31+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.StackHasher"));
32+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.ThrowableConverter"));
33+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.JsonEncoder"));
34+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.JsonWriter"));
35+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.simplelogger.encoder.SimpleLogger"));
36+
37+
38+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.JsonNames"));
39+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.CoreJsonStream"));
40+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.HybridBufferRecycler$XorShiftThreadProbe"));
41+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.HybridBufferRecycler"));
42+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.HybridBufferRecycler$StripedLockFreePool"));
43+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("io.avaje.json.stream.core.Recyclers$ThreadLocalPool"));
44+
45+
// check for optional SLF4JPlatformLogger
46+
Class<?> slfPlatform = access.findClassByName("org.slf4j.jdk.platform.logging.SLF4JPlatformLogger");
47+
if (slfPlatform != null) {
48+
RuntimeClassInitialization.initializeAtBuildTime(slfPlatform);
49+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("org.slf4j.jdk.platform.logging.SLF4JPlatformLoggerFactory"));
50+
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("org.slf4j.jdk.platform.logging.SLF4JSystemLoggerFinder"));
51+
}
52+
}
53+
54+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Args=--no-fallback \
2+
--features=io.avaje.simplelogger.graalvm.BuildInitialization

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<modules>
1818
<module>avaje-simple-json-logger</module>
1919
<module>avaje-simple-logger</module>
20+
<module>graalvm-feature</module>
2021
</modules>
2122

2223
</project>

0 commit comments

Comments
 (0)