JDK-8039776 : Introspector throws NullPointerException for subclasses' mismatched get/setter
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2014-04-09
  • Updated: 2014-07-29
  • Resolved: 2014-04-10
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.
JDK 8 JDK 9
8u20Fixed 9 b12Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)


A DESCRIPTION OF THE PROBLEM :
java.beans.Introspector.getBeanInfo() throws a NullPointerException if you have a pair of getTer()/setTer() methods in a base class; and a pair of getTer()/setTer() methods in a subclass (or auto-generated proxy); and getTer() return type is not exactly the same as setTer() argument type (in my case, getTer() returns Set and setTer() only accepts some Set sub-interface).

We caught that by using Introspector on javassist Proxies returned by Hibernate. We have our own set implementation but Hibernate demands the use of the java.util.Set, hence the mixed use of both that led to the discovery of this bug.

See the code sample.

REGRESSION.  Last worked in version 7u45

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See the code sample.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Bean info is returned.
ACTUAL -
NullPointerException is being thrown.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException
	at java.lang.Class.isAssignableFrom(Native Method)
	at java.beans.Introspector.isAssignable(Introspector.java:809)
	at java.beans.Introspector.processPropertyDescriptors(Introspector.java:705)
	at java.beans.Introspector.getTargetPropertyInfo(Introspector.java:553)
	at java.beans.Introspector.getBeanInfo(Introspector.java:428)
	at java.beans.Introspector.getBeanInfo(Introspector.java:262)
	at IntrospectorFail.main(IntrospectorFail.java:39)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.beans.Introspector;
import java.util.Set;

public class IntrospectorFail {
    public interface SetF<X> extends Set<X> { }

    public class Base {
        private SetF<Object> items;

        public Set<Object> getItems() {
            return items;
        }

        public void setItems(SetF<Object> items) {
            this.items = items;
        }
    }

    public class Child extends Base {
        public Set<Object> getItems() {
            return super.getItems();
        }

        public void setItems(SetF<Object> items) {
            super.setItems(items);
        }
    }

    public static void main(String[] args) throws Throwable {
        // OK
        Introspector.getBeanInfo(Base.class, Object.class, Introspector.USE_ALL_BEANINFO);
        // OK
        Introspector.getBeanInfo(Child.class, Base.class, Introspector.USE_ALL_BEANINFO);
        // BOOM
        Introspector.getBeanInfo(Child.class, Object.class, Introspector.USE_ALL_BEANINFO);
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
- Make sure getters' and setter' parameter/return class is exactly the same.
- Use stopClass = getSuperclass() (not applicable if error manifests inside a library)


Comments
It is regression introduced by the 8027648 fix in jdk8b117.
09-04-2014

The following method of the Introspector class must be fixed: private static boolean isAssignable(Class<?> current, Class<?> candidate) { return current == null ? candidate == null : current.isAssignableFrom(candidate); }
09-04-2014