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


Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to