You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Eric Westfall (JIRA)" <ji...@apache.org> on 2012/08/14 03:13:38 UTC
[jira] [Commented] (BEANUTILS-340) Property with getter from
generic interface returns wrong readMethod/propertyType on Linux
environment
[ https://issues.apache.org/jira/browse/BEANUTILS-340?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13433818#comment-13433818 ]
Eric Westfall commented on BEANUTILS-340:
-----------------------------------------
Considering there hasn't been any activity on this jira and Java 6 is EOL, what I'm about to say may not end up being too important. But if someone does have a chance to try and integrate this fix in, I think you will want to review the attached patch. We actually experienced firsthand that it can be disastrous under load. It manifests in such a way that you start getting random errors about getters not being found on objects which obviously have those getters. The general stack trace looks like this:
{code}
java.lang.NoSuchMethodException: Property 'blah' has no getter method in class 'class my.package.MyClass'
at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1340)
at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:752)
...
{code}
The main problem appears to be in these two lines:
{code}
descriptor.setReadMethod(null);
descriptor.setWriteMethod(null);
{code}
First of all, this appears to be modifying the state in an unsafe way of PropertyDescriptors that are cached and used by multiple threads. This is likely the source of the problem because what we are seeing is situations where we get back a PropertyDescriptor with a null readMethod in random cases and only under load.
Our "fix" was to remove these two lines where it sets the method to null because they really seemed unnecessary. While this appeared to work around the issue, I still think it's likely that there is some unsafe stuff going on here from a concurrency perspective since it's still modifying property descriptor read/write methods, but it should happen in far fewer cases if those lines above are omitted.
> Property with getter from generic interface returns wrong readMethod/propertyType on Linux environment
> ------------------------------------------------------------------------------------------------------
>
> Key: BEANUTILS-340
> URL: https://issues.apache.org/jira/browse/BEANUTILS-340
> Project: Commons BeanUtils
> Issue Type: Bug
> Components: Bean / Property Utils
> Affects Versions: 1.8.0-BETA
> Environment: ==Works correctly in==
> Windows XP
> java version "1.5.0_12"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04)
> Java HotSpot(TM) Client VM (build 1.5.0_12-b04, mixed mode)
> ==Fails in==
> Linux 2.6.27-gentoo-r8 #6 SMP Thu Feb 5 19:18:16 MST 2009 i686 06/17 GenuineIntel GNU/Linux
> java version "1.5.0_17"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_17-b04)
> Java HotSpot(TM) Server VM (build 1.5.0_17-b04, mixed mode)
> Reporter: Dave Lindquist
> Priority: Minor
> Fix For: LATER THAN 1.8.4
>
> Attachments: jira_340_new.patch, jira_340.patch
>
>
> PropertyUtils.getPropertyDescriptors is returning the wrong readMethod (and thus the wrong property type) when a method is implemented from a genericized interface, but only on some environments. This seems to work on Windows, but fails on Linux. (Compile environment does not matter, runtime environment does seem to matter.)
> Take the following test class:
> {code}
> public class Testing
> {
> public static void main(String[] args) throws Exception
> {
> for(PropertyDescriptor desc : PropertyUtils.getPropertyDescriptors(Test2.class))
> {
> if(desc.getName().equals("something"))
> {
> System.out.println(desc.getName() + "\t" + desc.getPropertyType() + "\t" + desc.getReadMethod() + "\t" + desc.getReadMethod().isSynthetic() + "\t" + desc.getReadMethod().isBridge());
> }
> }
> }
>
> // An interface with generics, and with getter and setter defined 'generically'.
> public static interface Test<T extends Number>
> {
> public T getSomething();
>
> public void setSomething(T something);
> }
>
> // A concrete class using a specific genericization of the interface (Long), with getter and setter implemented appropriately.
> public static class Test2 implements Test<Long>
> {
> public Long getSomething()
> {
> return(null);
> }
>
> public void setSomething(Long something)
> {
>
> }
> }
> }
> {code}
> When run on Windows XP, and working correctly, this prints:
> something class java.lang.Long public java.lang.Long Testing$Test2.getSomething() false false
> indicating that it got the 'long' version of the method, and that this method is NOT synthetic or a bridge method.
> However, when run on Linux, this prints:
> something class java.lang.Number public volatile java.lang.Number Testing$Test2.getSomething() true true
> which is the signature from the interface, and is marked with both synthetic and bridge, indicating that this is not the 'real' method, but the compiler-created method due to generics.
> I think that it should be ignoring the 'synthetic/bridge' method auto-created by the compiler, but I'm not sure why it is environment-dependent. Perhaps the environment somehow controls the method definition order? (At runtime, not compile time, obviously.)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira