On Sun, 2 Mar 2025 03:16:02 GMT, Jason Mehrens <[email protected]> wrote:
>> I'd have to disagree with the points you make.
>>
>> The fact is that loggers are never expected to modify the passed parameters.
>> To ask people to "disown" the parameters they pass to a logger requires that
>> your best advice on how to write a log statement with mutable values must
>> look something like:
>>
>>
>> if (logger.isEnabled(level)) {
>> // Avoid copying parameters when logging is disabled.
>> var arg1Copy = arg1.defensiveCopy();
>> var arg2Copy = arg2.defensiveCopy();
>> logger.log(level, "foo={0}, bar={1}", arg1Copy, arg2Copy);
>> }
>>
>>
>> as opposed to:
>>
>>
>> logger.log(level, "foo={0}, bar={1}", arg1, arg2);
>>
>>
>> The former is, in my opinion, a pretty awful user experience, error prone,
>> and (more to the point) something that almost nobody ever does in real code
>> because, reasonably, they trust the internal logger classes not to be
>> malicious.
>>
>> The comment about the record being owned by the logger means that it can't
>> be cached and reused, or passed to different log statements etc. It doesn't
>> give logging classes any freedom to modify the log statement parameters.
>>
>> The other issue with "defer processing to another thread", even if you do
>> format in the original thread, is that either:
>>
>> 1. You format just the arguments to strings -- Now things like `{0,date}`
>> are broken because you turned date/time arguments into strings what are no
>> longer formattable with the original format string.
>> 2. You format the entire message -- Now any handlers downstream cannot use
>> the format message (the thing with the placeholders in) as a key to identify
>> the log statements, which is sometimes really important for analysis.
>>
>> It's just really hard (maybe impossible) to create any general solution
>> where a log record (as opposed to some custom semi-flattened form) can be
>> safely used between threads without this being visible in some way to users.
>>
>> So my (personal) strong advice for Handler implementations is:
>> 1. Never let the log record you are given escape the call to `publish()`.
>> 2. You can store metadata from the log record "on the side", but only for
>> non user-supplied arguments.
>>
>> So, if you wanted to use something like `MemoryHandler`, subclass it and
>> override `publish()` to make new log records to pass into its queue, which
>> contain only flat formatted information (and even then you might break
>> assumptions of a downstream handler).
>>
>> However, if you are formatting everything in the `publish()` method, you
>> don't reall...
>
>>The former is, in my opinion, a pretty awful user experience...
>
> Specifically, I'm referring to this, with awareness of the above described
> limitations:
>
> //String.format is var-arg
> logger.log(Level.SEVERE, () -> { return String.format("foo=%s bar=%s", arg1,
> arg2); });
>
> //logger is not var-arg
> if (logger.isLoggable(lvl)) { //if arg1 and arg2 known to be never null
> logger.log(lvl, "foo={0} bar={1}", new Object[]{arg1.toString(),
> arg2.toString()});
> }
>
> //logger is not var-arg
> if (logger.isLoggable(lvl)) { //if arg1 and arg2 are nullable
> logger.log(lvl, "foo={0} bar={1}", new Object[]{Objects.toString(arg1),
> Objects.toString(arg2)});
> }
>
>
> How did you worked around this deadlock issue prior to this patch? That
> would be awesome information to add to the JIRA ticket for those that would
> like this patch but are unable to upgrade.
The only workaround is to early format parameters, either at the call site or
in the logger/handler.
This bug has been around for a very long time, and I suspect that it hasn't
been a serious issue for people because, in general, most toString()
implementations are non-locking and most log statements are disabled most of
the time. It's also a probabilistic deadlock which requires some instance to be
being accessed by two threads concurrently. I have however witnessed it causing
issues in real production systems.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/23491#discussion_r1977228065