-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
7u55
-
x86_64
-
windows_7
FULL PRODUCT VERSION :
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
When setters/getters of a bean class are generics based, PropertyDescriptors may lose information concerning the property type.
This happens whenever the (weak+soft) references of the PropertyDescriptor are cleared (as may be done at any time by the garbage collector).
This leads to extremly hard to find bugs, as test code typically will work fine (no GC of soft references yet) while production systems fail after some time.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the class test.Main as given in the test case.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
property type is class java.lang.Integer
Write method is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
property type after clear is class java.lang.Integer
Write method after clear is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
ACTUAL -
property type is class java.lang.Integer
Write method is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
property type after clear is class java.lang.Object
Write method after clear is public void test.Main$Bean.setSomeProperty(java.lang.Object)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
PropertyDescriptor pd = getTestPropertyDescriptor();
System.out.println("property type is " + pd.getPropertyType());
System.out.println("Write method is " + pd.getWriteMethod());
clearReferenceFieldsToSimulateGC(pd);
System.out.println("property type after clear is " + pd.getPropertyType());
System.out.println("Write method after clear is " + pd.getWriteMethod());
}
/** get PropertyDescriptor for "someProperty" via Introspector's Bean Info */
private static PropertyDescriptor getTestPropertyDescriptor() throws Exception {
for (PropertyDescriptor next : Introspector.getBeanInfo(Bean.class).getPropertyDescriptors()) {
if (next.getName().equals("someProperty")) {
return next;
}
}
throw new IllegalStateException();
}
/** clear 3 (weak or soft) reference fields in the given PropertyDescriptor object */
private static void clearReferenceFieldsToSimulateGC(PropertyDescriptor somePropertyDesc) throws Exception {
clearRef("writeMethodRef", somePropertyDesc);
clearRef("readMethodRef", somePropertyDesc);
clearRef("propertyTypeRef", somePropertyDesc);
}
private static void clearRef(String name, PropertyDescriptor somePropertyDesc) throws Exception {
Field refField = PropertyDescriptor.class.getDeclaredField(name);
refField.setAccessible(true);
Reference<?> writeMethodRef = (Reference<?>) refField.get(somePropertyDesc);
writeMethodRef.clear();
}
public static class Bean implements BeanInterface<Integer> {
private Integer someProperty;
@Override
public Integer getSomeProperty() {
return someProperty;
}
@Override
public void setSomeProperty(Integer someProperty) {
this.someProperty = someProperty;
}
}
public static interface BeanInterface<T> {
T getSomeProperty();
void setSomeProperty(T newProp);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Do not use generic types for bean setters and getters.
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
When setters/getters of a bean class are generics based, PropertyDescriptors may lose information concerning the property type.
This happens whenever the (weak+soft) references of the PropertyDescriptor are cleared (as may be done at any time by the garbage collector).
This leads to extremly hard to find bugs, as test code typically will work fine (no GC of soft references yet) while production systems fail after some time.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the class test.Main as given in the test case.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
property type is class java.lang.Integer
Write method is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
property type after clear is class java.lang.Integer
Write method after clear is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
ACTUAL -
property type is class java.lang.Integer
Write method is public void test.Main$Bean.setSomeProperty(java.lang.Integer)
property type after clear is class java.lang.Object
Write method after clear is public void test.Main$Bean.setSomeProperty(java.lang.Object)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
PropertyDescriptor pd = getTestPropertyDescriptor();
System.out.println("property type is " + pd.getPropertyType());
System.out.println("Write method is " + pd.getWriteMethod());
clearReferenceFieldsToSimulateGC(pd);
System.out.println("property type after clear is " + pd.getPropertyType());
System.out.println("Write method after clear is " + pd.getWriteMethod());
}
/** get PropertyDescriptor for "someProperty" via Introspector's Bean Info */
private static PropertyDescriptor getTestPropertyDescriptor() throws Exception {
for (PropertyDescriptor next : Introspector.getBeanInfo(Bean.class).getPropertyDescriptors()) {
if (next.getName().equals("someProperty")) {
return next;
}
}
throw new IllegalStateException();
}
/** clear 3 (weak or soft) reference fields in the given PropertyDescriptor object */
private static void clearReferenceFieldsToSimulateGC(PropertyDescriptor somePropertyDesc) throws Exception {
clearRef("writeMethodRef", somePropertyDesc);
clearRef("readMethodRef", somePropertyDesc);
clearRef("propertyTypeRef", somePropertyDesc);
}
private static void clearRef(String name, PropertyDescriptor somePropertyDesc) throws Exception {
Field refField = PropertyDescriptor.class.getDeclaredField(name);
refField.setAccessible(true);
Reference<?> writeMethodRef = (Reference<?>) refField.get(somePropertyDesc);
writeMethodRef.clear();
}
public static class Bean implements BeanInterface<Integer> {
private Integer someProperty;
@Override
public Integer getSomeProperty() {
return someProperty;
}
@Override
public void setSomeProperty(Integer someProperty) {
this.someProperty = someProperty;
}
}
public static interface BeanInterface<T> {
T getSomeProperty();
void setSomeProperty(T newProp);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Do not use generic types for bean setters and getters.
- relates to
-
JDK-8041555 PropertyDescriptor.getPropertyType() returns different class after GC
-
- Closed
-