JDK-8027905 : Wrong property type after GC clears method refs
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 7u40
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • Submitted: 2013-09-26
  • Updated: 2014-10-13
  • Resolved: 2013-11-06
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
1. Given a base class A or an Interface with a generic Parameter <P> and a getter and setter method for an Attribute of type P.

2. Given a derived class B extends A<AnyType> with a getter and setter method for AnyType which override the corresponding methods from the super class.

After the the method references in the property descriptor have been cleared (by gc normally) and you retrive the property type once more the type is determined wrong.

The following method list is a part of the result of B.class.getMethods()

Method: public java.lang.Object B.getFoo(); isSyntetic=true
Method: public java.lang.String B.getFoo(); isSyntetic=false
Method: public void B.setFoo(java.lang.Object); isSyntetic=true
Method: public void B.setFoo(java.lang.String); isSyntetic=false

Unfortunately the method "getPublicDeclaredMethods" of class Introspector does not filter out all the Abstract and syntetic methods and becasue the method "internalFindMethod" of class Introspector now takes the first getter method it uses "public java.lang.Object B.getFoo()" to determine the property type which is wrong!

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run the delivered test case

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
1. property type: class java.lang.String
2. property type: class java.lang.String

ACTUAL -
property type (before clear ref): class java.lang.String
property type (after clear ref): class java.lang.Object


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Super<T> {
public T getFoo() {
return null;
}

public void setFoo(T t) {
}
}

class Sub extends Super<String> {
@Override
public String getFoo() {
return null;
}

@Override
public void setFoo(String t) {
}
}

class Test {
public void run() {
PropertyDescriptor prop = getDescriptor("foo");

for (Method aMethod : Sub.class.getMethods()) {
System.out.println("Method: " + aMethod + "; isSyntetic=" + aMethod.isSynthetic());
}

System.out.println("");
System.out.println("property type (before clear ref): " + prop.getPropertyType());
clearMethodRef(prop, "readMethodRef");
clearMethodRef(prop, "writeMethodRef");
clearMethodRef(prop, "propertyTypeRef");
System.out.println("property type (after clear ref): " + prop.getPropertyType());
}

private void clearMethodRef(PropertyDescriptor theProp, String theRefName) {
try {
Field aField = PropertyDescriptor.class.getDeclaredField(theRefName);

aField.setAccessible(true);
Reference<Method> aReference = (Reference<Method>) aField.get(theProp);
aField.setAccessible(false);

aReference.clear();
}
catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException theCause) {
theCause.printStackTrace();
}
}

private PropertyDescriptor getDescriptor(String theName) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(Sub.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (PropertyDescriptor prop : propertyDescriptors) {
if (prop.getName().equals("foo")) {
return prop;
}
}
}
catch (IntrospectionException theCause) {
theCause.printStackTrace();
}
return null;
}
}

public class Bug {
public static void main(String[] args) {
new Test().run();
}

}
---------- END SOURCE ----------
Comments
It is not reproducible. It is fixed by the 7172865 change.
06-11-2013