JDK-8030126 : (ann) Unnecessary String allocation for instances of Annotations
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 5.0,6,7,8,9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2013-12-13
  • Updated: 2017-06-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_minorUnresolved
Related Reports
Relates :  
Description
In application, such as web services, where annotations are heavily used, there can be significantly large number of duplicate String instances resulting in cases where an annotation with the same type name and element string are used across a very large number of methods.

The effect is that there are a very large number duplicate String objects that get allocated and consume a significant portion of the Java heap. An example enterprise application using web services and annotations showed there is one annotation service namespace and element string duplicated 14,000 times.  If we were to avoid duplicating this single string for the service type, we would save 3MB.
In this particular application, there are 300,000+ similarly duplicated strings encompassing both annotation types and elements. If we were to eliminate all those duplicate strings arising from annotation types and elements in this app we would save 88MB.

Here is a trivial example that illustrates the issue, (also included as an example).
-- begin code --
import java.lang.reflect.Method;

import javax.xml.ws.RequestWrapper;

public class MyTestService {
	final static String tns = "MyTns";
	@RequestWrapper(targetNamespace=tns)
	public String myTestMethod(String input) {
		return input;
	}
	@RequestWrapper(targetNamespace=tns)
	public String myTestMethod2(String input) {
		return input;
	}
	public static void main(String args[]) throws NoSuchMethodException, SecurityException {
		MyTestService s = new MyTestService();
		Method m1 = s.getClass().getMethod("myTestMethod", java.lang.String.class);
		Method m2 = s.getClass().getMethod("myTestMethod2", java.lang.String.class);
		Method m3 = s.getClass().getMethod("myTestMethod", java.lang.String.class);
			
		RequestWrapper ann1 = m1.getAnnotation(RequestWrapper.class);
		RequestWrapper ann2 = m2.getAnnotation(RequestWrapper.class);
		RequestWrapper ann3 = m3.getAnnotation(RequestWrapper.class);
		
		System.out.println((m1 != m3) ? "getMethod returns different Method object for myTestMethod on 2 invocations" : "m1 == m3");
		
		System.out.println((ann1.targetNamespace() != ann3.targetNamespace()) ? 
				"Annotation on myTestMethod has 2 different String objects for targetNamespace attribute" : "");
		
		System.out.println((ann1.targetNamespace() != ann2.targetNamespace()) ? 
				"Annotations on myTestMethod1 and myTestMethod2 have 2 different String objects for targetNamespace attribute" : "");
	}
}
-- end code

In the above example, each call to m[1-3].getAnnotation(RequestWrapper.class) allocates a unique LinkedHashMap with a unique String instance of "targetNamespace" for the key, and a unique String instance of "myTns" for the value.  So, in this example, there are 3 unique distinct instances (copies) of String objects for "targetNamespace", and 3 unique distinct instance (copies) of String objects for "myTns".
Further, depending on the size / length of the annotation type, or more importantly, the length of the element, the amount of space consumed by creating duplicate String instances can explode very rapidly.

Ideally, there would be one String object instance for each annotation type and element.  It'd also be nice to reduce the number of LinkedHashMap allocated too.  But, that's a lesser issue than the number of duplicate Strings.

Comments
See JDK-8054987 for a partial solution
13-08-2014