You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When use DefaultCDI "load" to retrieve an instance dynamically in some rare ocasions we have an lock..
This only ocurrs on and concurrent threads environment because of the the DefaultCDI and DependencyMap classes..
DependencyMap.java uses an HashSet (lockedDependencies attribute) and DefaultCDI.java is using and HashMap on createDefaultProvidedData method.. Both are not thread safe..
Test case:
packagekikaha.core.cdi.helpers;
importkikaha.core.cdi.CDI;
importlombok.SneakyThrows;
importlombok.val;
importorg.junit.Test;
importjava.nio.channels.IllegalBlockingModeException;
importjava.nio.channels.IllegalChannelGroupException;
importjava.nio.channels.IllegalSelectorException;
importjava.util.*;
importjava.util.concurrent.Executors;
importstaticorg.junit.Assert.*;
publicclassDependencyMapTest {
staticbooleanshouldLoad = false;
List<Object> objects = Arrays.asList( Integer.MAX_VALUE, Long.MAX_VALUE, Double.MAX_VALUE, Boolean.FALSE, Float.MAX_VALUE,
newRuntimeException(), newIllegalAccessError(), newIllegalArgumentException(), newIllegalMonitorStateException(),
newIllegalStateException(), newIllegalThreadStateException(), newIllegalAccessException(), newIllformedLocaleException(),
newIllegalFormatPrecisionException(1), newIllegalFormatWidthException(1), newIllegalFormatCodePointException(1),
newIllegalChannelGroupException(), newIllegalSelectorException(), newIllegalBlockingModeException());
@Test@SneakyThrowspublicvoidmultiThreadsLockSimulation(){
valdependencyMap = newDependencyMap( createDefaultProvidedData() );
valpool = Executors.newCachedThreadPool();
for ( valobject : objects ) {
valclazz = object.getClass();
valinstanceCollection = Collections.singletonList(object);
pool.submit(() -> {
try {
System.out.println("Starting thread for class " + clazz);
while (true) {
if (shouldLoad)
break;
Thread.sleep(1);
}
dependencyMap.put(clazz, instanceCollection);
dependencyMap.unlock(clazz);
System.out.println("Ending thread for class " + clazz);
} catch (Throwablee) {
System.out.println("ERR " + e);
}
});
}
Thread.sleep( 2000 );
shouldLoad = true;
Thread.sleep( 2000 );
System.out.println( "Check..." );
for ( valobject : objects ) {
valclazz = object.getClass();
try {
valloadedCollection = dependencyMap.get(clazz);
assertNotNull("No lock but null for class " + clazz, loadedCollection);
assertEquals(object, first(loadedCollection));
} catch ( DependencyMap.TemporarilyLockedExceptionlockError ){
fail( "Lock exception for class " + clazz );
}
}
}
/** Same contents from DefaultCDI#createDefaultProvidedData */protectedMap<Class<?>, Iterable<?>> createDefaultProvidedData() {
// XXX: 50% of the solution// final Map<Class<?>, Iterable<?>> injectable = new ConcurrentHashMap<>();finalMap<Class<?>, Iterable<?>> injectable = newHashMap<>();
injectable.put( CDI.class, newSingleObjectIterable<>( this ) );
returninjectable;
}
private <T> Tfirst(Iterable<T> instances) {
returninstances.iterator().next();
}
}
Running this code, most of the time we have different erros.. Some examples: java.lang.AssertionError: Lock exception for class class java.lang.Integer java.lang.AssertionError: Lock exception for class class java.lang.Long java.lang.AssertionError: No lock but null for class class java.lang.Double java.lang.AssertionError: No lock but null for class class java.lang.IllegalAccessException
This problem is critical because when this happends there is a infinite loop when use load:
Thread-safe solution
DependencyMap.java
Alter from new HashSet<>() to ConcurrentHashMap.newKeySet()
DefaultCDI.java
Alter from new HashMap<>() to new ConcurrentHashMap<>()
The text was updated successfully, but these errors were encountered:
When use DefaultCDI "load" to retrieve an instance dynamically in some rare ocasions we have an lock..
This only ocurrs on and concurrent threads environment because of the the DefaultCDI and DependencyMap classes..
DependencyMap.java
uses anHashSet
(lockedDependencies
attribute) andDefaultCDI.java
is using and HashMap oncreateDefaultProvidedData
method.. Both are not thread safe..Test case:
Running this code, most of the time we have different erros.. Some examples:
java.lang.AssertionError: Lock exception for class class java.lang.Integer
java.lang.AssertionError: Lock exception for class class java.lang.Long
java.lang.AssertionError: No lock but null for class class java.lang.Double
java.lang.AssertionError: No lock but null for class class java.lang.IllegalAccessException
This problem is critical because when this happends there is a infinite loop when use
load
:Thread-safe solution
DependencyMap.java
Alter from
new HashSet<>()
toConcurrentHashMap.newKeySet()
DefaultCDI.java
Alter from
new HashMap<>()
tonew ConcurrentHashMap<>()
The text was updated successfully, but these errors were encountered: