22

If you look at the source code of Sun's implementation of Class.getSimpleName(), you'll notice it seems to return a new instance of String each and every time you call it. Many other features in the Class class is however cached.

Since the simple name computation does not seem to be easy and there's nothing in the JavaDoc to say it has to return a new instance every time, it should be a good candidate for caching. I am wondering could there be any design reason why this is not cached?

I am asking because many frameworks use simple names all the time and this is such an easy thing to cache.

billc.cn
  • 7,187
  • 3
  • 39
  • 79
  • 6
    Caching it would increase the memory held by every class, for a questionable performance gain. – JB Nizet Jun 28 '13 at 16:24
  • You could always add your own caching using `AspectJ` if you wanted to. – selig Jun 28 '13 at 16:35
  • @JBNizet But for any non-array type, the operation is a sub-string of a potentially intern'ed string which does not require much extra memory. – billc.cn Jun 28 '13 at 17:41
  • Seems like this is a question to ask Sun, not SO. – Hot Licks Jun 28 '13 at 18:57
  • 2
    **It *is* cached**, at least in Java 12. See the OpenJDK source code for [`Class.java`](https://hg.openjdk.java.net/jdk/jdk12/file/0276cba45aac/src/java.base/share/classes/java/lang/Class.java) and search for `private ReflectionData reflectionData()` method called from the `getSimpleName` method. – Basil Bourque Feb 23 '19 at 04:07
  • Here is the issue @BasilBourque mentioned https://bugs.openjdk.java.net/browse/JDK-8187123 – Philippe Marschall Aug 23 '19 at 10:58

3 Answers3

8

Update: Name cached in OpenJDK 11

The class name is cached, in OpenJDK 11 and later.

See the OpenJDK source code for Class.java. Search for private ReflectionData<T> reflectionData() method called from the getSimpleName method.

For details, see ticket JDK-8187123.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

Probably because it's not an expensive method, so there's not much to gain in caching it.

String.substring is a cheap method -- it reuses the underlying char[] without copying it, and the new String object just has a different offset and length into that array. So really the only costs are (1) the object allocation -- which is pretty cheap in Java -- and (2) the lastIndexOf call. That call is technically O(N), but N here is the class's simple name, which is not going to be very large in practice.

You could cache it, but at the cost of more memory. My guess would be that someone made the subjective but educated guess that the benefits don't outweigh the costs.

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • 4
    The most significant cost here won't be the substring(), but the other methods that are called in order to get the string to sub-string. There are `getSimpleBinaryName()` which unconditionally calls `getEnclosingClass()` which calls `getEnclosingMethodInfo()`, etc. The whole process does not look very cheap to me. – billc.cn Jun 28 '13 at 17:46
  • @billc.cn I don't know, it all terminates at native methods like `getEnclosingMethod0()`. Hard to know how cheap or expensive it is. – yshavit Jun 28 '13 at 18:08
  • 1
    `substring` *sometimes* uses the underlying char array -- it depends on the specific implementation. – Hot Licks Jun 28 '13 at 18:56
  • @HotLicks The OP asked about Sun's implementation and linked to code in a specific version (openjdk-6-b14). I was assuming that context in my answer. – yshavit Jun 28 '13 at 19:36
  • 5
    I want to point out that this is no longer true. Java 7 made substring actually copy the underlying string. https://stackoverflow.com/questions/16123446/java-7-string-substring-complexity . I've profiled plenty of Java 8 server applications at LinkedIn where accessing a class's simple name used a good chunk of CPU (between 5-10%) due to this fact. – Joshua Hartman Jul 14 '17 at 20:11
1

Interesting question. Since String is an immutable class, it doesn't really matter if you return distinct instances or a reference to the same object. My guess would be (and I'm giving it mostly to hear if I'm right or wrong) that maybe the method is not called very often and it makes more sense to re-create the (String) object than to store it in memory. But again, this is just a guess.

user2520968
  • 358
  • 1
  • 3
  • 11