Description
We are working to make Log4j 2 garbage-free and we are using the Allocation Instrumenter in our unit tests to verify that we don't allocate objects during steady state logging.
We see our tests randomly fail with this exception:
Exception in thread "Thread-0" java.lang.NullPointerException
at com.google.monitoring.runtime.instrumentation.AllocationRecorder.getObjectSize(AllocationRecorder.java:200)
at com.google.monitoring.runtime.instrumentation.AllocationRecorder.recordAllocation(AllocationRecorder.java:244)
at java.util.Hashtable.getEnumeration(Hashtable.java:665)
at java.util.Hashtable.keys(Hashtable.java:329)
at java.util.logging.LogManager$LoggerContext.getLoggerNames(LogManager.java:688)
at java.util.logging.LogManager.reset(LogManager.java:1135)
at java.util.logging.LogManager$Cleaner.run(LogManager.java:248)
I believe this is a bug in AllocationRecorder:
The NullPointerException above occurs when the (java.util.logging) LogManager$Cleaner shutdown hook allocates a new object and the instrumented bytecode invokes the recordAllocation method.
The AllocationRecorder also has a shutdown hook which sets its instrumentation field to null.
These shutdown hook threads can run at the same time, so if the instrumentation field is set to null after the null check (line 236) but before it is used in getObjectSize (line 200), we get the above exception.
One solution would be to introduce a local Instrumentation variable, assign the value of the static instrumentation field to the local variable, and do the null check on that local variable. If non-null, call the getObjectSize method with the local Instrumentation variable as one of the parameters. The getObjectSize method would use the passed Instrumentation parameter and should not access the static field.