OGNL Expression中如何使用URLClassloader和反射

How to use URLClassloader and reflection in OGNL Expression

我将 URLClassLoader 与 OGNL 表达式一起使用,它将加载一个远程 jar 文件。 然而,有一个例外:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1244)
    at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1349)
    at ognl.ASTMethod.getValueBody(ASTMethod.java:90)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTChain.getValueBody(ASTChain.java:141)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTAssign.getValueBody(ASTAssign.java:52)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTSequence.getValueBody(ASTSequence.java:63)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.Ognl.getValue(Ognl.java:494)
    at ognl.Ognl.getValue(Ognl.java:644)
    at ognl.Ognl.getValue(Ognl.java:702)
    at ognl.Ognl.getValue(Ognl.java:672)

这是我的代码

Ognl.getValue("#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL('http://*.*.*.*/wd.jar')}),#lc=#cl.loadClass('Hello'),#o=#lc.getConstructor().newInstance(),#m=#lc.getDeclaredMethod('hello'),#m.invoke(#o,null)",

Web日志显示URLClassLoader访问了jar文件,但是我调用的函数没有正常工作。

xxxxxxxx - - [28/Jul/2015:07:19:38 -0400] "GET /wd.jar HTTP/1.1" 200 613 "-" "Java/1.7.0_51" "-"

这是为什么?

这是因为 getConstructorgetDeclaredMethod 方法中的可变参数。 OGNL 对可变参数的处理不是很好。

您可以重写表达式以避免可变参数。您无需调用构造函数来获取新实例,并且一旦拥有实例,就无需在 OGNL 中使用反射。 :)

Ognl.getValue("#cl=new java.net.URLClassLoader(new java.net.URL[]{"
    + " new java.net.URL('http://*.*.*.*/wd.jar')}), #lc=#cl.loadClass('Hello'),"
    + " #o=#lc.newInstance(), #o.hello()", context);

顺便说一句,你的 Hello class 是默认包吗?您需要在 loadClass 中提供 FQN(例如 loadClass('some.package.Hello'))。