Applications can be multi-threaded. I believe we load the DefaultConfiguration so other threads aren’t blocked by Log4j initialization. The statement that “no logging can possibly occur until after at least said construction” isn’t true.
Ralph > On Dec 27, 2022, at 12:12 PM, Matt Sicker <m...@musigma.org> wrote: > > In this particular scenario, a file URI has been provided to the > LoggerContext constructor. Given the fact that a Logger instance itself is > not constructed until _after_ the LoggerContext has been constructed, no > logging can possibly occur until at least after said construction. In our > current implementation, we always load a DefaultConfiguration in > LoggerContext before reconfiguring to use the real config. > > This applies to any possible ContextSelector, by the way, since those control > the creation of LoggerContext instances in the first place (unless you’re > using something lower level to start things up like one of the LoggerContext > constructors I’m referring to, but that’s always handled by the underlying > ContextSelector in Core). The Java memory model guarantees that constructing > a class is an atomic operation; the result of the constructor is safely > published and available for any and all threads to consume. This is the main > reason why using the `final` keyword is useful in Java: final fields in > classes are the safely published state (assuming the underlying reference is > an immutable or thread-safe structure of course), and volatile fields require > memory fencing before doing any reads or writes to them in order for threads > to all see the same state. In theory, we may be able to load a configuration > during the constructor which would help avoid all those weird hacks in place > by Spring Boot et al. for disabling logging until they can bootstrap > themselves first. > — > Matt Sicker > >> On Dec 19, 2022, at 08:11, Ralph Goers <ralph.go...@dslextreme.com> wrote: >> >> I am not really sure what the question here is. When you pass in a >> configuration location you are going to end up with a LoggerContext that >> references a Configuration derived from the information at that location. >> Yes, it may create a DefaultConfiguration along the way but that is >> primarily because logging may need to occur while Log4j is configuring. >> >> As for the external context, that was initially created to support binding >> with things like Spring. However, the way Spring Boot ended up using it >> caused some issues for adding extended Spring support so the LoggerContext >> now contains a Map so that multiple “external” values can be captured. The >> ExternalContext is just stored in a specific key. Given how the injector >> worked the last time I looked at it I don’t really see how Spring could use >> it. >> >> Ralph >> >> >> >>> On Dec 18, 2022, at 12:29 PM, Matt Sicker <m...@musigma.org> wrote: >>> >>> So I’m working on the properties enhancement issue, and one thing I’ve come >>> across to clean up are the situations where the LoggerContext may be null >>> in the constructor to AbstractConfiguration. Previously, this only seemed >>> to be the case for NullConfiguration, but it may also apply to >>> DefaultConfiguration during startup. However, suppose I construct a >>> LoggerContext with a configuration location corresponding to a file (so the >>> only supported file path type via that constructor). This location does not >>> get used until the LoggerContext starts; before this, it constructs a >>> DefaultConfiguration. >>> >>> During this bootstrapping, if the configuration location is available (such >>> as for a unit test), should LoggerContext set up the configuration >>> provided? Or is there some sort of cyclic dependency here preventing us >>> from loading ConfigurationFactory right away? So far, the only cyclic >>> dependencies I’ve found are related to plugins created in the >>> DefaultConfiguration (or the NullConfiguration in some cases), but those >>> are already commented as such (like in PatternLayout). >>> >>> I’ll note for reference that LoggerContext has two families of constructors >>> that fan out into the following parameters: >>> >>> String name, Object externalContext, String/URI configLocation, Injector >>> injector, PropertyResolver propertyResolver -> LoggerContext >>> >>> The external context concept here seems to mainly be used for passing along >>> a ClassLoader instance or something derived from it (I think a Bundle does >>> or something from OSGi at least). These constructors do call >>> Injector::init, so the point of providing an Injector instance here would >>> be if you preconfigured some beans (like in a unit test) before wanting to >>> load the default bundles of beans/bindings. >>> — >>> Matt Sicker >>> >> >