hg: jdk8/tl/jdk: 7194897: JSR 292: Cannot create more than 16 instances of an anonymous class; ...

Peter Levart peter.levart at gmail.com
Thu Nov 7 08:36:14 UTC 2013

On 11/07/2013 02:20 AM, John Rose wrote:
> On Nov 6, 2013, at 11:30 AM, Peter Levart <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>> wrote:
>> Well, indexOf(char) or lastIndexOf(char) searches for a single char. 
>> We can do better searching backwards for two chars at the same time.
>> If the "name" of VM-anonymous class is always ending with pattern: 
>> "slash followed by some decimal digits" then the following would be 
>> even faster:
> Although this reasoning is plausible, it is not a reliable conclusion, 
> and should not drive edits of Java code without careful measurement. 
>  The reasoning assumes a performance model based on the interpreter 
> and bytecode count.  But performance depends on native code produced 
> by the JIT.

I agree. I should have measured it...

> An optimizing JIT will usually transform the code deeply.  For string 
> scanning, for example, HotSpot has an intrinsic for 
> String.indexOf(String) that uses totally different code from a 
> user-coded loop.  (It is not currently so for String.indexOf(int), but 
> String.indexOf("/") is potentially very fast.)
> Also, with your example code, the combined loop may often be faster 
> than two back-to-back loops, but simpler loops can sometimes be 
> vectorized more robustly, to the point where back-to-back simple 
> loops, if vectorized, may be competitive with a hand-fused loop.
> So loop complexity and method intrinsics can create surprises for 
> those who rely on simple performance modesl
> Some day we will get to a world where loops are specified stream-wise, 
> and robustly optimized without this sort of manual intervention.  In 
> the mean time, be careful about advising hand-optimizations of Java 
> code.  They can backfire, by confusing the JIT and preventing 
> optimizations that would apply to simpler code.
> — John

So I did measure it. I took two classes with the following names:


Typically package names will be even relatively longer than in this example.

I measured the following implementations:

     public static boolean isVMAnonymousClass(Class<?> cls) {
         return cls.getSimpleName().contains("/");

     public static boolean isVMAnonymousClass_FAST1(Class<?> cls) {
         String name = cls.getName();
         for (int i = name.length() - 1; i >= 0; i--) {
             char c = name.charAt(i);
             if (c == '.') return false;
             if (c == '/') return true;
         return false;

     public static boolean isVMAnonymousClass_FAST2(Class<?> cls) {
         String name = cls.getName();
         for (int i = name.length() - 1; i >= 0; i--) {
             char c = name.charAt(i);
             if (c == '/') return true;
             if (c < '0' || c > '9') return false;
         return false;

     public static boolean isVMAnonymousClass_indexOf(Class<?> cls) {
         return cls.getName().indexOf("/") > -1;

I also tried String.lastIndexOf(String) and it is a little faster for 
true return, since it only scans backwards until the "/" is found, but 
it is slower than String.indexOf(String) for "false" return. Is it not 

Here are the results:


I think that any of the above implementations that doesn't use 
Class.getSimpleName() is good. The FAST2 variant is favourable for false 
return since it typically decides after examining a single character at 
end of class name and is still among the fastest for true return...

Here's the code I used for testing:


Regards, Peter

More information about the core-libs-dev mailing list