Question

I'm currently working with a specialized, interpreted, programming language implemented in Java. As a very small part of the language, I'd like to add the ability to make calls into Java. Before I dive into all of the nitty-gritty of reflection, I was wondering if anyone knew of a general library for doing the "backend" part of invoking Java code reflectively.

That is, I parse a string (I define the grammar) into some data structure that represents a Java method call (or constructor, or field access) and then pass that data structure to this library that invokes the call and returns the result. In particular, I'd like it to already handle all the edge cases that I don't want to figure out:

  • Automagically pick the right method based on the types of arguments (like an intelligent Class.getDeclaredMethod())
  • Handle distinction between arrays and normal object references
  • etc

I've spent a little time looking at the implementations of dynamic languages on the JVM, but these are generally much more complicated than I'm looking for, or highly optimized for the particular language.

Another option is to convert my grammar into a string in some dynamic language and invoke it with Rhino or something, but that's a little more overhead than I'm looking for.

Thanks!

Was it helpful?

Solution

Just a comment to your own answer; actually beanutils has support for getting "a close match" given a set of parameters. See getMatchingAccessibleMethod()

BeanUtils is really powerful and has lots of utility methods for inspecting classes. The same support is naturally available for constructors.

OTHER TIPS

Try the FEST Reflection module. It's a fluent way to do Java reflection. For example:

 String name = method("get").withReturnType(String.class)
                         .withParameterTypes(int.class)
                         .in(names)
                         .invoke(8);

If you're looking for simplicity, I have created a simple library called jOOR in order to facilitate access to the reflection API in Java. It supports the most essential actions without building up a huge API. Here's an example of what jOOR code looks like:

String world = 
on("java.lang.String") // Like Class.forName()
.create("Hello World") // Call the most specific matching constructor
.call("substring", 6)  // Call the most specific matching substring() method
.call("toString")      // Call toString()
.get()                 // Get the wrapped object, in this case a String

Take a look at Java's scripting support; I believe it will help you tackle your problem.

Have a look at Apache Commons BeanUtils

I would strongly consider also having a look at springs ReflectionUtils class. Very powerful reflection handling.

TO raise this from the dead:

invoke(Object object, String methodName, Object[] args) 

Apache Commons lang has exactly that method. MethodUtils#invoke

I have started to create a library com.lexicalscope.fluent-reflection:fluent-reflection which integrates with hamcrest and lambdaj

You can write code like this; which calls all the post construct annotated methods in a class:

forEach(
   object(subject).methods(annotatedWith(PostConstruct.class)),
   ReflectedMethod.class).call();

Blog post here: http://www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

Documentation here: http://fluent-reflection.lexicalscope.com/

You can get it from maven central here: http://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

It has some basic features missing at the moment, like access to fields, but it works for methods. It will probably take a while to get to a really feature stable point (like a year or two), as I am only working on it occasionally. But it is developed to quite a high quality standard (I hope) and it is opensource so you can basically use it as it is now if it has all the features you need (you just might have to adjust your code a bit if you want to use newer versions that are released). I am using it in some production code at them moment.

It is designed to be quite extensible, so you can plugin in strategies to find the methods you want in a loosely coupled (compositional) style. So if it doesn't have the exact method lookup strategy you want, hopefully it is easy to add it.

I ended up going with Alex's suggestion. BeanUtils helps a lot for beans, but I don't want to work solely with Beans. FEST looks really cool and I've bookmarked it for further study, but like BeanUtils, it doesn't appear to solve what I consider to be the difficult problem here. Namely, given a method name and list of arguments, pick the method that best "fits" the arguments. If a method takes a float and I have a double, it should be smart enough to not reject that method because the signature doesn't match exactly.

Obviously, scripting languages built on the JVM solve this problem, but in a much more complicated way than I need due to language-specific optimizations. So, since this is a minor and experimental feature, I've chosen an expeditious solution using the scripting engine support (JavaScript, in particular) in Java 1.6. Here's the basic idea:

private ScriptEngine engine = ... initialize with JavaScript engine ...

private Object invoke(Object object, String methodName, Object[] args) 
   throws RhsFunctionException
{
   // build up "o.method(arg0, arg1, arg2, ...)"
   StringBuilder exp = new StringBuilder("o." + methodName);
   engine.put("o", object);
   buildArgs(arguments, exp);

   try {
      return engine.eval(exp.toString());
   }
   catch (ScriptException e) {
      throw new RhsFunctionException(e.getMessage(), e);
   }
}

private void buildArgs(Object[] args, StringBuilder exp)
{
   // Use bindings to avoid having to escape arguments
   exp.append('(');
   int i = 0;
   for(Symbol arg : args) {
         String argName = "arg" + i;
         engine.put(argName, arg);
         if(i != 0) {
            exp.append(',');
         }
         exp.append(argName);
         ++i;
   }
   exp.append(')');
}

There's obviously a bit more to it, but this is the basic idea. I don't really like building up a string and evaluating it, but by using the bindings suggested by Alex, I avoid most of the pitfalls around escaping. Furthermore, I have a clean, simple interface that I can swap out with a "real" implementation if it proves necessary.

Any feedback or alternate solutions are more than welcome.

I wrote and open-sourced this code after reading this thread, maybe you can find it useful.

https://github.com/yclian/Reflects.java/blob/master/src/test/java/my/jug/reflects/ReflectsTest.java

It's inspired by Guava, so you can use Predicate to filter the methods you like.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top