8 Replies Latest reply on Feb 17, 2009 6:05 PM by Scott Stark

    JBREFLECT-50, determining need for setAccessible bug

    Scott Stark Master

      I ran into a curious behavior I either never knew, or forgot regarding access permissions via reflection. In order for a method to be accessible via reflection without calling setAccessible on the method, both the method and the class have to be public. A public method in a non-public class cannot be accessed by the resulting java.lang.reflect.Method object. It fails with an java.lang.IllegalAccessException like that shown on JBREFLECT-50. I also show the required change to allow the ReflectMethodInfoImpl to determine when a call to setAccessible is needed.

      I'm going to need a new jboss-reflect release for the current work I'm doing on JBAS-6285. Its the jdk platform mbeans that are instances of non-public classes implementing a public interface that I cannot create valid ManagedObjects for because of this issue. Can I do a 2.0.3.GA release to pickup this fix for inclusion into jbossas 5.1.x?

        • 1. Re: JBREFLECT-50, determining need for setAccessible bug
          Scott Stark Master

          Note that to integrate with the current security manager check done in setMethod, the fix should be something like this rather than what I show on the jira issue:

           public void setMethod(Method method)
           {
           boolean callSetAccessible = false;
           if (method != null)
           {
           int classModifiers = method.getDeclaringClass().getModifiers();
           boolean isPublic = isPublic() && Modifier.isPublic(classModifiers);
           accessCheck(isPublic);
           callSetAccessible = !isPublic;
           }
          
           this.method = method;
          
           if (callSetAccessible)
           setAccessible();
           }
          



          • 2. Re: JBREFLECT-50, determining need for setAccessible bug
            David Lloyd Master

            Since the class is implementing a public interface, can't you get the Method from the interface instead of the class?

            • 3. Re: JBREFLECT-50, determining need for setAccessible bug
              Scott Stark Master

              We would have to do a lot more work to identify methods that are part of an interface as its not readily available from the Class or Method objects. I did test that if you obtain the Method object from the interface that this can be used to reflect on the instance of the non-public class without having to call setAccessible.

              A proper fix would probably have to consider whether methods belong to an interface or else when running under a security manager one would have to grant ReflectPermission("suppressAccessChecks") to contexts that should not need it.

              • 4. Re: JBREFLECT-50, determining need for setAccessible bug
                Scott Stark Master

                And speaking of running under a security manager, the SetAccessible PrivilegedAction in ReflectMethodInfoImpl should not be used because the security check should not be based on the jboss-reflect codebase. It needs to be based on the codebase calling into the reflection layer, and in reality, the code that is actually doing the invocation.

                I can see a general jboss layer like the management layer needing to obtain the reflection view, but the determination as to whether setAccessible can be called should be done when the invocation is made to validate that the caller codebase wanting to access or set a property value is not bypassing the underlying bean class java language security declarations.

                • 5. Re: JBREFLECT-50, determining need for setAccessible bug
                  Scott Stark Master

                  I worked around it for the JBAS-6285 case by updating the managed object factory to accept an interface that is to be used for the BeanInfo generation.

                  • 6. Re: JBREFLECT-50, determining need for setAccessible bug
                    Scott Stark Master

                    I think the correct solution is to add a new BeanAccessMode.INTERFACES enum value that indicates that only methods matching interfaces the bean implements will be incorporated into the BeanInfo result. This should then be the default mode for non-public classes?

                    • 7. Re: JBREFLECT-50, determining need for setAccessible bug
                      Scott Stark Master

                      A problem with the workaround of obtaining the BeanInfo using the interface the bean implements is that the IntrospectionTypeInfoFactoryImpl.getSuperClass does not return the superinterface for an interface. Obtaining a BeanInfo for an interface like java.lang.management.GarbageCollectorMXBean which extends java.lang.management.MemoryManagerMXBean fails to include the MemoryManagerMXBean properties:

                       public void testGarbageCollectorMXBeanIface()
                       throws Throwable
                       {
                       BeanInfo info = super.getBeanInfo(GarbageCollectorMXBean.class, BeanAccessMode.ALL);
                       PropertyInfo name = info.getProperty("name");
                       assertNotNull(name);
                       }
                      
                      ...
                      
                      java.lang.IllegalArgumentException: No such property name for bean java.lang.management.GarbageCollectorMXBean available [collectionCount, collectionTime]
                       at org.jboss.beans.info.plugins.AbstractBeanInfo.getProperty(AbstractBeanInfo.java:147)
                       at org.jboss.test.beaninfo.test.PlatformMXBeanTestCase.testGarbageCollectorMXBeanIface(PlatformMXBeanTestCase.java:47)
                      


                      name is a property in the MemoryManagerMXBean interface.

                      Is this expected or a limitation of the current BeanInfo reflection implementation?


                      • 8. Re: JBREFLECT-50, determining need for setAccessible bug
                        Scott Stark Master

                        For now I have worked around this in the AbstractManagedObjectFactory by iterating over all of the interfaces the interface the managed object claims to implement to build up the full BeanInfo.