2
votes

I want to load Java class using URLClassLoader and invoke method main. The code below gives an error at the last line and I can not figure out how to fix it.


(def classloader (URLClassLoader. (into-array files)))

(def classname "example.Test")
(def clazz (.. classloader (loadClass classname)))

; I assume not the most effective way to get method "main" 
; additional feedback appreciated
(def method (first (filter #(= (. % getName) "main") (. clazz getMethods))))

(def args (make-array String 1))
; specify single command line argument for method main(String[]args)
(aset args 0 "my-file")

; attempt to invoke static method using Java reflection API fails.
(. method invoke nil args)


Exception in thread "main" java.lang.IllegalArgumentException: 
argument type mismatch, compiling:

Please note that the class is not otherwise available in the default classloader, so


 (example.Test/main "myfile")

would fail.

Thank you, Pavel

2

2 Answers

1
votes

You are confusing the signature of invoke with the signature of the main method.

The signature of "main" is (String[] args1) The signature of "invoke" is (Object obj, Object... args2)

args2 should be an array with one item per each param in the main method, so it should be an array of 1 element, the element being the String[]. So:

(def invoke-args (into-array Object [args]))
(. method invoke nil invoke-args)

About a simpler way of finding "main" look at http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getMethod(java.lang.String,%20java.lang.Class...)

0
votes

I summarized the result of the discussion below. (Thanks to dAni for help).

    (let
      [classname "example.Test"
       clazz (.. classloader (loadClass classname))

   method (. clazz getMethod "main" (into-array Class [(class (into-array String []))]))

   args (make-array String 1)]
  (aset args 0 "my-file")
  (. method invoke nil (into-array Object [args])))