5555import java .util .Set ;
5656import java .util .Map ;
5757import java .util .concurrent .ConcurrentHashMap ;
58- import java .util .concurrent .ConcurrentLinkedQueue ;
5958import java .util .concurrent .ConcurrentSkipListMap ;
59+ import java .util .concurrent .ConcurrentSkipListSet ;
6060import java .util .stream .Collectors ;
6161import java .util .stream .Stream ;
6262
7171@ AutomaticallyRegisteredFeature
7272public final class DynamicAccessDetectionFeature implements InternalFeature {
7373
74+ // We use a ConcurrentSkipListMap, as opposed to a ConcurrentHashMap, to maintain
75+ // order of methods by access kind.
7476 public record MethodsByAccessKind (Map <DynamicAccessDetectionPhase .DynamicAccessKind , CallLocationsByMethod > methodsByAccessKind ) {
7577 MethodsByAccessKind () {
7678 this (new ConcurrentSkipListMap <>());
@@ -85,7 +87,9 @@ public CallLocationsByMethod getCallLocationsByMethod(DynamicAccessDetectionPhas
8587 }
8688 }
8789
88- public record CallLocationsByMethod (Map <String , ConcurrentLinkedQueue <String >> callLocationsByMethod ) {
90+ // We use a ConcurrentSkipListSet, as opposed to a wrapped ConcurrentHashMap, to maintain
91+ // order of call locations by method.
92+ public record CallLocationsByMethod (Map <String , ConcurrentSkipListSet <String >> callLocationsByMethod ) {
8993 CallLocationsByMethod () {
9094 this (new ConcurrentSkipListMap <>());
9195 }
@@ -94,8 +98,8 @@ public Set<String> getMethods() {
9498 return callLocationsByMethod .keySet ();
9599 }
96100
97- public ConcurrentLinkedQueue <String > getMethodCallLocations (String methodName ) {
98- return callLocationsByMethod .getOrDefault (methodName , new ConcurrentLinkedQueue <>());
101+ public ConcurrentSkipListSet <String > getMethodCallLocations (String methodName ) {
102+ return callLocationsByMethod .getOrDefault (methodName , new ConcurrentSkipListSet <>());
99103 }
100104 }
101105
@@ -136,7 +140,7 @@ public static DynamicAccessDetectionFeature instance() {
136140 public void addCall (String entry , DynamicAccessDetectionPhase .DynamicAccessKind accessKind , String call , String callLocation ) {
137141 MethodsByAccessKind entryContent = callsBySourceEntry .computeIfAbsent (entry , k -> new MethodsByAccessKind ());
138142 CallLocationsByMethod methodCallLocations = entryContent .methodsByAccessKind ().computeIfAbsent (accessKind , k -> new CallLocationsByMethod ());
139- ConcurrentLinkedQueue <String > callLocations = methodCallLocations .callLocationsByMethod ().computeIfAbsent (call , k -> new ConcurrentLinkedQueue <>());
143+ ConcurrentSkipListSet <String > callLocations = methodCallLocations .callLocationsByMethod ().computeIfAbsent (call , k -> new ConcurrentSkipListSet <>());
140144 callLocations .add (callLocation );
141145 }
142146
0 commit comments