diff --git a/core/src/main/java/org/jruby/RubyClass.java b/core/src/main/java/org/jruby/RubyClass.java index 6c687fbf779..33e2354c1e5 100644 --- a/core/src/main/java/org/jruby/RubyClass.java +++ b/core/src/main/java/org/jruby/RubyClass.java @@ -93,7 +93,7 @@ import org.jruby.util.Loader; import org.jruby.util.OneShotClassLoader; import org.jruby.util.StringSupport; -import org.jruby.util.collections.ConcurrentWeakHashMap; +import org.jruby.util.WeakIdentityHashMap; import org.jruby.util.log.Logger; import org.jruby.util.log.LoggerFactory; import org.objectweb.asm.AnnotationVisitor; @@ -1019,7 +1019,14 @@ protected void setModuleSuperClass(RubyClass superClass) { @JRubyMethod public IRubyObject subclasses(ThreadContext context) { - RubyArray subs = RubyArray.newArray(context.runtime); + Map subclasses = this.subclasses; + int sizeEstimate = subclasses == null ? 0 : subclasses.size(); + + if (sizeEstimate == 0) { + return RubyArray.newEmptyArray(context.runtime); + } + + RubyArray subs = RubyArray.newArray(context.runtime, sizeEstimate); concreteSubclasses(subs); @@ -1081,18 +1088,18 @@ private void subclassesInner(Collection mine, boolean includeDescenda } } - private void concreteSubclasses(Collection subs) { + private void concreteSubclasses(RubyArray subs) { Map subclasses = this.subclasses; if (subclasses != null) { - Set keys = subclasses.keySet(); - for (RubyClass klass: keys) { - if (klass.isSingleton()) continue; - if (klass.isIncluded() || klass.isPrepended()) { - klass.concreteSubclasses(subs); - continue; + subclasses.forEach((klass, $) -> { + if (!klass.isSingleton()) { + if (klass.isIncluded() || klass.isPrepended()) { + klass.concreteSubclasses(subs); + } else { + subs.append(klass); + } } - subs.add(klass); - } + }); } } @@ -1112,7 +1119,7 @@ public void addSubclass(RubyClass subclass) { synchronized (this) { subclasses = this.subclasses; if (subclasses == null) { - this.subclasses = subclasses = new ConcurrentWeakHashMap<>(4, 0.75f, 1); + this.subclasses = subclasses = Collections.synchronizedMap(new WeakIdentityHashMap(4)); } } }