Konstantin, On 5/1/12 11:04 AM, Christopher Schultz wrote: > On 4/28/12 8:58 PM, Konstantin Kolinko wrote: >> >> I am OK with your proposal, but I do not expect much savings from >> getting rid of those duplicates. Does YouKit show some estimates? > > It did, but I closed it long ago so I'll have to re-check. IIRC, it was > a couple of MiB. Of course, it's not feasible to check 100% of them > because there were so many copies. I can hack a bit at Tomcat and see > what percentage of them disappear. Then I'll know whether such a change > in Tomcat actually has a meaningful impact.
YourKit shows 1123 copies of "java.lang.String" for a "waste" of 89760 bytes. Sure, that's nothing. But, I don't have much in the way of stuff loaded. With multiple webapps, hosts, etc. I suspect that numebr will just go up. Let's see how much can be attributed to Tomcat's MBeans... I can see that the following fields retain references to duplicate "java.lang.String" strings: org.apache.tomcat.util.modeler.AttributeInfo.type org.apache.tomcat.util.modeler.OperationInfo.type javax.management.MBeanOperationInfo.type javax.management.MBeanAttributeInfo.attributeType (I'll have to look at where we create those last two to see if we can pass-in a shared reference to "java.lang.String"). There are 883 instances of AttributeInfo and I assume that all of them are using duplicate strings. o.a.t.u.m.MbeansDescriotorsIntrospectionSource.createManagedBean creates new AttributeInfo objects in this code (trunk, starting at line 302): Enumeration<String> en = attMap.keys(); while( en.hasMoreElements() ) { String name = en.nextElement(); AttributeInfo ai=new AttributeInfo(); ai.setName( name ); Method gm = getAttMap.get(name); if( gm!=null ) { //ai.setGetMethodObj( gm ); ai.setGetMethod( gm.getName()); Class<?> t=gm.getReturnType(); if( t!=null ) ai.setType( t.getName() ); } Method sm = setAttMap.get(name); if( sm!=null ) { //ai.setSetMethodObj(sm); Class<?> t = sm.getParameterTypes()[0]; if( t!=null ) ai.setType( t.getName()); ai.setSetMethod( sm.getName()); } ai.setDescription("Introspected attribute " + name); if( log.isDebugEnabled()) log.debug("Introspected attribute " + name + " " + gm + " " + sm); if( gm==null ) ai.setReadable(false); if( sm==null ) ai.setWriteable(false); if( sm!=null || gm!=null ) mbean.addAttribute(ai); } In either case, the "type" of the AttributeInfo is coming from Class.getName, which I would have expected to be interned. The Method values in attMap come directly from Class.getMethods() so it should all be coming from the JVM's RTTI. I checked ran a very simple test and found that Class.getMethods returns a new set of objects every time it is called (at least in my environment: MacOSX/Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)). I must admit I'm a little surprised that Class.getMethods doesn't cache the Method objects it creates. Anyhow, the Class objects that are used for Method.getReturnType *are* shared, and the return values from those are also shared (so, String.class.getMethod("compareTo", {String.class}) returns parameter and return types that are == to each other, and calling Class.getName on each of those returns String values that are == to each other). I'm going to keep looking. -chris
signature.asc
Description: OpenPGP digital signature