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
>>> 
>> 
> 

Reply via email to