99soft/sli4j — pull request #3 by ginkel (2012-07-10 14:06:38+00:00)
Title: Fix race condition in AbstractLoggerInjector

The existing AbstractLoggerInjector implementation was not thread-safe as
concurrent injections in multiple threads were corrupting each other's
field.accessible status (field is shared between all threads using the same
Injector).

The result were exceptions like this:

com.google.inject.ProvisionException: Guice provision errors:

1) Impossible to set logger for field 'private java.lang.Object org.nnsoft.guice.sli4j.core.ConcurrentInjectionTest$InjectionTarget.logger', see nested exception: Class org.nnsoft.guice.sli4j.core.AbstractLoggerInjector can not access a member of class org.nnsoft.guice.sli4j.core.ConcurrentInjectionTest$InjectionTarget with modifiers "private"
while locating org.nnsoft.guice.sli4j.core.ConcurrentInjectionTest$InjectionTarget

1 error
at com.google.inject.internal.Errors.throwProvisionExceptionIfErrorsExist(Errors.java:451)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:65)
at com.google.inject.internal.InjectorImpl.injectMembers(InjectorImpl.java:944)
at org.nnsoft.guice.sli4j.core.ConcurrentInjectionTest.injectAndVerify(ConcurrentInjectionTest.java:34)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:74)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:673)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:846)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1170)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.internal.thread.ThreadUtil$CountDownLatchedRunnable.run(ThreadUtil.java:147)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

The fix is to make the field accessible during the AbstractLoggerInjector
construction (where the execution path is single-threaded), which is what
Google is also doing in
com.google.inject.internal.SingleFieldInjector#SingleFieldInjector.

Concurrent test case included.