Skip to content

Commit

Permalink
Make ReflectionSupport.findNestedClasses thread-safe
Browse files Browse the repository at this point in the history
ReflectionSupport.findNestedClasses(..)` is now thread-safe with regard
to cycle detection.

Closes #2715
  • Loading branch information
sbrannen committed Sep 18, 2021
1 parent 7896665 commit 3242bf6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ GitHub.

==== New Features and Improvements

* ❓
* `ReflectionSupport.findNestedClasses(..)` is now thread-safe with regard to cycle
detection.


[[release-notes-5.8.1-junit-jupiter]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -130,7 +130,7 @@ public enum HierarchyTraversalMode {
* @since 1.6
* @see #detectInnerClassCycle(Class)
*/
private static final Set<String> noCyclesDetectedCache = new HashSet<>();
private static final Set<String> noCyclesDetectedCache = ConcurrentHashMap.newKeySet();

/**
* Internal cache of common class names mapped to their types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.stream.Stream;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -787,11 +788,14 @@ void findNestedClassesWithSeeminglyRecursiveHierarchies() {
*/
@Test
void findNestedClassesWithRecursiveHierarchies() {
assertNestedCycle(OuterClass.class, InnerClass.class, OuterClass.class);
assertNestedCycle(StaticNestedClass.class, InnerClass.class, OuterClass.class);
assertNestedCycle(RecursiveInnerClass.class, OuterClass.class);
assertNestedCycle(RecursiveInnerInnerClass.class, OuterClass.class);
assertNestedCycle(InnerClass.class, RecursiveInnerInnerClass.class, OuterClass.class);
Runnable runnable1 = () -> assertNestedCycle(OuterClass.class, InnerClass.class, OuterClass.class);
Runnable runnable2 = () -> assertNestedCycle(StaticNestedClass.class, InnerClass.class, OuterClass.class);
Runnable runnable3 = () -> assertNestedCycle(RecursiveInnerClass.class, OuterClass.class);
Runnable runnable4 = () -> assertNestedCycle(RecursiveInnerInnerClass.class, OuterClass.class);
Runnable runnable5 = () -> assertNestedCycle(InnerClass.class, RecursiveInnerInnerClass.class,
OuterClass.class);
Stream.of(runnable1, runnable1, runnable1, runnable2, runnable2, runnable2, runnable3, runnable3, runnable3,
runnable4, runnable4, runnable4, runnable5, runnable5, runnable5).parallel().forEach(Runnable::run);
}

private static List<Class<?>> findNestedClasses(Class<?> clazz) {
Expand Down

0 comments on commit 3242bf6

Please sign in to comment.