-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
6u14
-
x86
-
linux
FULL PRODUCT VERSION :
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
I've reproduced this on several Linux 64bit machines. Here is the uname string from my laptop, which runs Ubuntu 9.04
Linux nitrobenzol 2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC 2009 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
When using the BeanInfo returned from java.beans.Introspector, calling getWriteMethod() on a single instance of PropertyDescriptor does not always return the same Method. I've only seen this behaviour after memory shortage (probably related to the use of soft/weak references within PropertyDescriptor). See below for sample code that demonstrates the problem. The bad thing about this is that in my situation it surfaced only after running a system for a couple of days. Suddenly, the system failed with NPEs
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run attached demonstration code and examine output.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I'd expect the program to print this:
Write method is public void c1.setPage(page)
Write method abstract false
Write method is public void c1.setPage(page)
Write method is public void c1.setPage(page)
Write method is public void c1.setPage(page)
Write method abstract false
ACTUAL -
Write method is public void c1.setPage(page)
Write method abstract false
Write method is public void c1.setPage(page)
Write method is public abstract void i1.setPage(page)
Write method is public abstract void i1.setPage(page)
Write method abstract true
(Note the sudden change in the return value. The problem doesn't occur when you comment the bomb() call that simulates memory shortage)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.util.*;
import java.lang.reflect.*;
class page {
}
class pagesub extends page {
}
interface i1 {
page getPage();
void setPage(page page);
}
class c1 implements i1 {
public page getPage() {
return null;
}
public void setPage(page page) {
}
}
class c2 extends c1 implements i1 {
public pagesub getPage() {
return null;
}
}
public class proptest {
public static void main(String[] args) {
try {
PropertyDescriptor pd = getDescriptor();
if (pd == null) {
System.err.println("Failed to obtain page property descriptor.");
return;
}
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method abstract " +
Modifier.isAbstract(pd.getWriteMethod().getModifiers()));
bomb();
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method abstract " +
Modifier.isAbstract(pd.getWriteMethod().getModifiers()));
return;
} catch (Exception e) {
System.err.println("exception: " + e);
e.printStackTrace();
}
}
public static void bomb() {
try {
Collection<byte[]> c = new LinkedList<byte[]>();
while (true) {
c.add(new byte[1]);
}
} catch (OutOfMemoryError e) {
System.gc();
return;
}
}
public static PropertyDescriptor getDescriptor() {
c2 obj = new c2();
PropertyDescriptor pd = null;
try {
BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
for (PropertyDescriptor d : bi.getPropertyDescriptors()) {
if ("page".equals(d.getName())) {
pd = d;
}
}
} catch (IntrospectionException e) {
System.err.println("IntrospectionException: " + e);
}
return pd;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Several:
- Don't use the pagesub type when overriding getPage(), but use page instead
- Provide a setter within c2
- Drop the implements i1 in the declaration of c2
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
I've reproduced this on several Linux 64bit machines. Here is the uname string from my laptop, which runs Ubuntu 9.04
Linux nitrobenzol 2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC 2009 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
When using the BeanInfo returned from java.beans.Introspector, calling getWriteMethod() on a single instance of PropertyDescriptor does not always return the same Method. I've only seen this behaviour after memory shortage (probably related to the use of soft/weak references within PropertyDescriptor). See below for sample code that demonstrates the problem. The bad thing about this is that in my situation it surfaced only after running a system for a couple of days. Suddenly, the system failed with NPEs
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run attached demonstration code and examine output.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I'd expect the program to print this:
Write method is public void c1.setPage(page)
Write method abstract false
Write method is public void c1.setPage(page)
Write method is public void c1.setPage(page)
Write method is public void c1.setPage(page)
Write method abstract false
ACTUAL -
Write method is public void c1.setPage(page)
Write method abstract false
Write method is public void c1.setPage(page)
Write method is public abstract void i1.setPage(page)
Write method is public abstract void i1.setPage(page)
Write method abstract true
(Note the sudden change in the return value. The problem doesn't occur when you comment the bomb() call that simulates memory shortage)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.util.*;
import java.lang.reflect.*;
class page {
}
class pagesub extends page {
}
interface i1 {
page getPage();
void setPage(page page);
}
class c1 implements i1 {
public page getPage() {
return null;
}
public void setPage(page page) {
}
}
class c2 extends c1 implements i1 {
public pagesub getPage() {
return null;
}
}
public class proptest {
public static void main(String[] args) {
try {
PropertyDescriptor pd = getDescriptor();
if (pd == null) {
System.err.println("Failed to obtain page property descriptor.");
return;
}
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method abstract " +
Modifier.isAbstract(pd.getWriteMethod().getModifiers()));
bomb();
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method is " + pd.getWriteMethod());
System.out.println("Write method abstract " +
Modifier.isAbstract(pd.getWriteMethod().getModifiers()));
return;
} catch (Exception e) {
System.err.println("exception: " + e);
e.printStackTrace();
}
}
public static void bomb() {
try {
Collection<byte[]> c = new LinkedList<byte[]>();
while (true) {
c.add(new byte[1]);
}
} catch (OutOfMemoryError e) {
System.gc();
return;
}
}
public static PropertyDescriptor getDescriptor() {
c2 obj = new c2();
PropertyDescriptor pd = null;
try {
BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
for (PropertyDescriptor d : bi.getPropertyDescriptors()) {
if ("page".equals(d.getName())) {
pd = d;
}
}
} catch (IntrospectionException e) {
System.err.println("IntrospectionException: " + e);
}
return pd;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Several:
- Don't use the pagesub type when overriding getPage(), but use page instead
- Provide a setter within c2
- Drop the implements i1 in the declaration of c2
- duplicates
-
JDK-6422403 Bean introspection does not correctly calculate types of inherited properties
- Closed