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