Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows和Linux中继承方法上的Java反射是否不同?_Java_Windows_Linux_Reflection - Fatal编程技术网

Windows和Linux中继承方法上的Java反射是否不同?

Windows和Linux中继承方法上的Java反射是否不同?,java,windows,linux,reflection,Java,Windows,Linux,Reflection,在设置Hudson进行持续集成测试(在JeOS服务器上)时,我遇到了一些奇怪的行为,我希望SO的优秀人员能向我解释 我们的单元测试严重依赖于域对象的使用,必须设置许多属性(由于数据库中的空约束)。为了保持测试的可读性,我们创建了一个类InstantiationUtils,它可以实例化一个对象并通过反射设置一系列属性: public static <T> T newInstance(final Class<T> type, final KeyValuePair<?&g

在设置Hudson进行持续集成测试(在JeOS服务器上)时,我遇到了一些奇怪的行为,我希望SO的优秀人员能向我解释

我们的单元测试严重依赖于域对象的使用,必须设置许多属性(由于数据库中的空约束)。为了保持测试的可读性,我们创建了一个类InstantiationUtils,它可以实例化一个对象并通过反射设置一系列属性:

public static <T> T newInstance(final Class<T> type, final KeyValuePair<?>... propertyValues) {

    return ReflectionUtils.reflectionOperation(new ReflectionOperation<T>() {

        @Override
        public T perform() throws Exception {

            T object = type.newInstance();
            for (KeyValuePair<?> propertyValue : propertyValues) {

                String propertyName = propertyValue.getKey();
                Object value = propertyValue.getValue();
                String setterName = "set" + StringUtils.capitalize(propertyName);
                ReflectionUtils.invoke(object, setterName, value);
            }
            return object;
        }
    });
}

public static void invoke(final Object target, final String methodName, final Object... params) {

    List<Class<?>> parameterTypes = ListUtils.map(asList(params), "class");
    Class<?> targetClass = target.getClass();
    Method method = MethodUtils.getMatchingAccessibleMethod(targetClass, methodName,
        parameterTypes.toArray(new Class<?>[] {}));
    invoke(target, method, params);
}

public class Foo {
    private String foo;

    public void setFoo(final String foo) {
        this.foo = foo;
    }
}

public class Bar extends Foo {
    private String bar;

    public void setBar(final String bar) {
       this.bar = bar;
    }
}
publicstatict newInstance(最终类类型、最终键值对…属性值){
返回ReflectionUtils.reflectionOperation(新的reflectionOperation(){
@凌驾
public T perform()引发异常{
T object=type.newInstance();
for(KeyValuePair propertyValue:propertyValue){
字符串propertyName=propertyValue.getKey();
对象值=propertyValue.getValue();
String setterName=“set”+StringUtils.capitalize(propertyName);
invoke(对象、setterName、值);
}
返回对象;
}
});
}
公共静态void调用(最终对象目标、最终字符串methodName、最终对象…参数){
List targetClass=target.getClass();
Method=MethodUtils.getMatchingAccessibleMethod(targetClass,methodName,
toArray(新类[]{});
调用(目标、方法、参数);
}
公开课Foo{
私人字符串foo;
公共void setFoo(最终字符串foo){
this.foo=foo;
}
}
公共类Bar扩展了Foo{
私人弦杆;
公共空心立根杆(最终弦杆){
这个.bar=bar;
}
}
不幸的是,编写这段代码的人已经不再为我们工作了,但据我所知,这段代码没有什么问题。对于Windows也是如此-我们在整个单元测试中使用实例化utils,没有任何问题


然而,Linux则不同。事实证明,在Linux中,newInstance()方法只适用于我们要实例化的类的直接(即非继承)成员

实例化utils.newInstance(Bar.class,“Bar”,“12345”);将在实例化utils.newInstance(Bar.class,“foo”,“98765”)时工作;将在Linux上失败,但以下情况除外:

xxx.xxx.xxx.ReflectionUtils$ReflectionException:java.lang.NoSuchMethodException:属性“foo”没有setter方法

在Windows上,这两个调用都可以工作(我知道newInstance签名不匹配;我们有几个重载的newInstance()方法将参数转换为KeyValuePairs)

我很难接受继承的公共方法会受到不同的对待,所以我已经用我能想到的所有方法对此进行了测试。最后总是得出结论,在Linux下,至少在上面使用反射的情况下,我们无法访问公共继承方法

在Windows上,我使用Sun的JRE 1.6.0.11,在Linux上也是Sun,但版本是1.6.0.7

有人能确认这是否正确吗?或者反射使用是否存在某种缺陷?

可能是不同Java运行时之间的设置不同吗

当然,我怀疑这是一个平台问题——几乎可以肯定这与两个环境之间的JRE版本/设置有关


您确实需要将源代码发布到MethodUtils.getMatchingAccessibleMethod

您在Linux、Sun、GCJ等上使用哪种JVM?如果您使用的不是Sun的JVM,您可以尝试安装它,看看这是否有区别。

您有不同的地区吗
StringUtils.capitalize(propertyName)
可能会产生不同的输出。

您使用的是MethodUtils,它有一些:

已知的限制

在默认访问超类中访问公共方法

调用默认访问超类中包含的公共方法时会出现问题。反射可以很好地定位这些方法,并正确地将它们指定为公共。但是,如果调用该方法,则会引发IllegalAccessException


要检查的另一件事是,如果setFoo()方法重载,这也可能会导致问题…

是否检查了
类路径?您是否根据所处的平台选择要实例化的类的不同版本?(例如,到处都是旧的代码库等?)

有几件事需要尝试

在Linux上,尝试在没有对getFoo()的反射调用的情况下编译代码-如果它无法编译,那么反射就没有工作的希望(这取决于yoiu在运行时如何设置CLASSAPTH…)

尝试添加下面的代码,并在Linux和Windows上运行

final Properties properties;

properties = System.getProperties();

for(final Entry<Object, Object> entry : properties.entrySet())
{
    System.out.println(entry.getKey() + " " + entry.getValue());
}
最终属性;
properties=System.getProperties();
for(最终条目:properties.entrySet())
{
System.out.println(entry.getKey()+“”+entry.getValue());
}

检查输出以确保您使用的是smae JDK/JRE。还要检查以确保类路径正确,以便实际加载您认为正在加载的内容。

谜团部分解决:

getMatchingAccessibleMethod()显然在Linux和Windows上的工作方式不同

通过改为使用MethodUtils.getAccessibleMethod(),它可以正常工作。为什么,我不知道,但我猜MethodUtils在计算方法应该具有什么签名时,以某种方式误解了参数列表

我想花更多的时间来研究这一点,但总是有事情要做,有项目要交付,所以我必须接受getAccessibleMethod的工作原理,然后继续:-)


感谢大家的投入

您是否在两个操作系统上使用相同版本的JRE?这听起来比操作系统更可能导致差异。还有,如果你能浓缩