5

Short version: I need to find a way in Java to locate the previous Method in the call stack (note the capital 'M' in Method--I need the actual java.lang.reflect.Method object).

Background: I'm working on an extension to the Google Guava Preconditions.checkNotNull(...) concept that will allow the programmer to simultaneously check ALL of the parameters for null, and construct an NPE based on the parameter names of the calling method. For example:

public class MyClass
{
    public void myMethod(Object arg1, Integer arg2, String arg3)
    {
        MyPreconditions.checkAllNotNull(arg1, arg2, arg3);
    }
}

So if the first argument was null, then the NPE might read arg1 cannot be null (MyClass:myMethod(Object, Integer, String)

I've already worked out how to get the calling Class and I can get the parameter names via the Spring LocalVariableTableParameterNameDiscoverer (or via the Paranamer library) one I have the Method. The only part that I can't figure out is how to get Method itself.

I'm aware that you can use the stack trace to get the method name, but that doesn't help if the method is overridden. Is there a way (even with internal com.sun classes) to get the actual stack? Alternatively, I can get the line number for the calling method, so is there a way to find the line number of a Method as retrieved from the Class object?

1

2 Answers 2

3

Thread.getStackTrace() gives you the current stacktrace. From there you can get the class name and method name (even if the method is overridden, you will see the exact class there), and get the method through reflection.

But imo - this is strange and not needed. And thing about it - you are providing a message that is mostly already present in the stacktrace that will be generated if the Preconditions call fails.

9
  • You can't consistently resolve the Method object if the class comes from another classloader, however.
    – Dolda2000
    Commented Mar 26, 2012 at 22:17
  • Well you can get the trace directly from the Throwable, something like: try{throw new Exception("deliberate");} catch(Exception e){ e.getStackTrace(); }. But agreed that it is somewhat odd to need it ...
    – user268396
    Commented Mar 26, 2012 at 22:18
  • @Dolda2000 which is what the getClassLoader() method of Class objects is for. Either you get a valid ClassLoader instance or you get null which means the boot loader. Then you take it from there... ?
    – user268396
    Commented Mar 26, 2012 at 22:20
  • @user268396 Sure, but the stacktrace doesn't give you Class objects, but just class names, and what I meant is that there is no consistent way to resolve Class objects from names, which would be the first necessary step to resolve Method objects from a stack trace.
    – Dolda2000
    Commented Mar 26, 2012 at 22:21
  • @Dolda2000 True, you would need to do it from inside a Class for which the classloader has access to the actual Class in some way --or at least to delegate classloader's that will co-operate nicely.
    – user268396
    Commented Mar 26, 2012 at 22:28
1

"I'm aware that you can use the stack trace to get the method name, but that doesn't help if the method is overridden." -- The stack trace contains the class name (and source file) as well, though, in a manner that is correct even if the method has been overridden.

I don't think there is any (good, consistent) way to get the actual Method object. Particularly not one that works with an active security manager. The Java security code itself uses some tricks to do that, but replicating that would not be portable between various VMs.

Not the answer you're looking for? Browse other questions tagged or ask your own question.