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

Reduce XML classes in native image when using Logback #33324

Open
sdeleuze opened this issue Nov 23, 2022 · 7 comments
Open

Reduce XML classes in native image when using Logback #33324

sdeleuze opened this issue Nov 23, 2022 · 7 comments
Labels
status: blocked An issue that's blocked on an external project change theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Milestone

Comments

@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 23, 2022

As discussed with @wilkinsona, in an empty Spring Boot application with just spring-boot-starter compiled to native, the only place where XML parsing is reachable is ch.qos.logback.core.joran.GenericXMLConfigurator#doConfigure. The impact on the footprint and compile time is quite significant (as usual with XML on native images).

On my Linux machine, the RSS memory after startup is 36.58M when XML is reachable and 34.15M without (difference of 2.43M or 6.64%). You can see the impressive diff of the 675 additional classes included in the native image in this gist.

To track how it is reachable, I compile the native image with a META-INF/native-image/native-image.properties with Args = -H:ReportAnalysisForbiddenType=ch.qos.logback.core.joran.event.SaxEventRecorder and it gives me the following stacktrace:

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(org.xml.sax.InputSource) 
Parsing context:
   at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:177)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:159)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
   at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:260)
   at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:237)
   at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:80)
   at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
   at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332)
   at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
   at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
   at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)

Sadly, GenericXMLConfigurator#doConfigure is final so we can't override it in a proper way, so to make the XML parsing not reachable for testing purpose, I used this substitution:

@TargetClass(className = "ch.qos.logback.core.joran.GenericXMLConfigurator")
final class Target_GenericXmlConfigurator {

	@Substitute
	public final void doConfigure(URL url) throws JoranException {
	}
}

I don't expect this to be fixable before Spring Boot 3.0 GA, but maybe we could do something about it in 3.0.x. We could potentially raise a related issue on Logback side to see if there is a possibility to make this method non final, or to ask a refactoring that would allow us to make the XML parsing not reachable on native image (either out of the box or via an override on Boot side).

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 23, 2022
@mhalbritter mhalbritter added type: enhancement A general enhancement theme: aot An issue related to Ahead-of-time processing and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 23, 2022
@mhalbritter mhalbritter added this to the 3.0.x milestone Nov 23, 2022
@mhalbritter mhalbritter changed the title Make Logback XML parsing not reachable at runtime on native images Unnecessary XML classes when using Logback in native images Nov 23, 2022
@mhalbritter mhalbritter added type: bug A general bug and removed type: enhancement A general enhancement labels Nov 23, 2022
@mhalbritter mhalbritter changed the title Unnecessary XML classes when using Logback in native images Unnecessary XML classes in native image when using Logback Nov 23, 2022
@wilkinsona
Copy link
Member

wilkinsona commented Nov 23, 2022

We can avoid this specific path with a small change to LogbackLoggingSystem:

diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
index 3cd3c241f7..63c8e85af3 100644
--- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
@@ -55,6 +55,7 @@ import org.springframework.boot.logging.LoggingInitializationContext;
 import org.springframework.boot.logging.LoggingSystem;
 import org.springframework.boot.logging.LoggingSystemFactory;
 import org.springframework.boot.logging.LoggingSystemProperties;
+import org.springframework.core.NativeDetector;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.env.ConfigurableEnvironment;
@@ -228,6 +229,9 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanF
        @Override
        protected void loadConfiguration(LoggingInitializationContext initializationContext, String location,
                        LogFile logFile) {
+               if (NativeDetector.inNativeImage()) {
+                       throw new IllegalStateException("Loading configuration in a native image is not supported.");
+               }
                if (initializationContext != null) {
                        applySystemProperties(initializationContext.getEnvironment(), logFile);
                }

Unfortunately, that just moves us onto the next one:

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(org.xml.sax.InputSource) 
Parsing context:
   at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:177)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:159)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
   at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
   at ch.qos.logback.classic.joran.ReconfigureOnChangeTask.performXMLConfiguration(ReconfigureOnChangeTask.java:113)
   at ch.qos.logback.classic.joran.ReconfigureOnChangeTask.run(ReconfigureOnChangeTask.java:73)
   at java.lang.Shutdown.runHooks(Shutdown.java:130)
   at java.lang.Shutdown.shutdown(Shutdown.java:185)
   at com.oracle.svm.core.jdk.RuntimeSupport.shutdown(RuntimeSupport.java:154)

I can't see a way to avoid this in Boot without some changes to Logback.

@sdeleuze
Copy link
Contributor Author

Yeah, I reached the same conclusion. Maybe we could mark this issue as blocked and we raise a related issue or PR on Logback side to discuss the possible options?

@wilkinsona
Copy link
Member

Sounds good to me.

@wilkinsona wilkinsona added the status: blocked An issue that's blocked on an external project change label Nov 23, 2022
@philwebb
Copy link
Member

@sdeleuze Did a Logback issue get raised for this?

@sdeleuze
Copy link
Contributor Author

Thanks for the reminder, I have created https://jira.qos.ch/browse/LOGBACK-1717.

@ceki
Copy link

ceki commented Apr 4, 2023

@sdeleuze Unfortunately, we had a server failure involving data loss. I have recreated issue LOGBACK-1717 by hand. If you wish to follow this item, you may need to sign in anew at jira.qos.ch.

On the bright side, this item is at the top of my to-do list.

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Apr 5, 2023

@ceki Thanks I will, feel free to reach me for feedback if needed, we can even plan a call if that can help.

@philwebb philwebb modified the milestones: 3.0.x, 3.1.x Nov 8, 2023
@wilkinsona wilkinsona changed the title Unnecessary XML classes in native image when using Logback Reduce XML classes in native image when using Logback May 20, 2024
@wilkinsona wilkinsona added type: enhancement A general enhancement and removed type: bug A general bug labels May 20, 2024
@wilkinsona wilkinsona modified the milestones: 3.1.x, 3.x May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: blocked An issue that's blocked on an external project change theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

6 participants