I am trying to get the caller class and method name inside a function in a Scala app. I am currently making use of the stack trace, but the performance has decreased. I am doing something like
stackTrace(CodeDepth).getClassName
stackTrace(CodeDepth).getMethodName
I have found the Java reflection to be a lot more faster, but i can only get the class name with
sun.reflect.Reflection.getCallerClass(CodeDepth).getName()
Is there a way to get the method name (and optionally the line number) via reflection? Maybe using Scala's reflection?
Thanks
Unfortunately, there is no non-expensive method to do this. There is a Java Enhancement Proposal to add a better alternative, but this doesn't help unless you can wait until Java 9 (and it isn't guaranteed to be included anyway).
On the other hand, is this really a hotspot in your code? This should only matter if it's called in a loop, and in this case you probably can call it once and cache the result.
For Scala you can just use the sourcecode library from https://github.com/lihaoyi/sourcecode and just do something like:
def log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {
println(s"${file.value}:${line.value} $foo")
}
log("Foooooo") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo
Related
I know (at least using either BCEL, or ASM, for instance), it is possible to somehow access local variables of a method... but, I need something more, what I would like is:
to get the type of such a variable (or a way to convert from the signature)
to know (distinguish) when this variable is used (either sees it value affected, or is passed as parameter)
when this variable is used as parameter, to know which method call it was passed to
to break "method-chains" in their respective method calls and get their return value so I can manipulate them
The basic idea is that I would like to "instrument" methods a bit in the same way a debugger does (though limited to the first frame depth...).
Any pointer appreciated.
If more information need, feel free to ask.
This is only possible using a byte code-level API. cglib does not expose such an API such that you have to choose between ASM, BCEL and Javassist where I would recommend you ASM which has the best documentation.
What you would need to do:
Parse the signature of the method, ASM offers utilities for that. You would get any type by its internal name. You would need to map these names to their index.
Find any use of the variable that is used from that index.
This is however a quite difficult task. In order to predict your code, you would have to emulate the method invocation. The JVM is a stack machine, arguments can be placed on the operand stack as a result of an arbitrary chain of commands. Therefore, you would effectively have to interpret any byte code instruction that you find. You will, more or less, need to write your own simplistic interpreter what is quite a task.
I am building a generic visualizer of objects with GWT. For this, I am using the reflection capabilities offered by gwt-ent. With it I can explore methods and fields and that's enough for classes. One problem I still have is that gwt-ent does not allow me to explore arrays. It gives me the type of its components, but not a get() or a set() method, as java.lang.reflection.Array does.
So I have used the native java.lang.reflection.Array, which curiously works when in debug mode (how is that possible?), but when I go into production mode the compiler complains.
I have tried some tricks, for instance by converting the array to an ArrayList with java.utils.Array.asList(T... a) but there's not way for making it work. I have seen a similar problem here. In that case one of the suggestion was to import the JSNI method provided byt com.google.gwt.lang.Array.createFrom(..), but I can see in the source code that this class unfortunately has a set() method but no get() method !
The question is: do you see any way for accessing an element of an array without knowing the type of the array in advance?
Reflection is not supported in GWT compiled. It can work in dev-mode because most of the code when debugging is run in JVM instead of browser.
I suggest, to modify the gwt-ent generator to match your requirements and send a patch to the author with your contribution, or maybe change gwt-ent by other 3party library like gwt-reflector.
Another interesting gwt reflection project I've found is gwt-processor it seems not to use generators.
I'm investigating ways to ensure a java class only calls a limited set of allowed methods from other classes. The usecase I have receives the class via the standard java serialization.
The approach I want to try is to simply list the methods it calls and only run the code if it passes a short whire list.
The question I have : how do I list the methods used in that class?
This is not a perfect solution but you coud use this if you can't find something better. You can use javap, if you're in Linux, run in the command line (or run a proccess using Runtime.exec()): javap -verbose /path/to/my/classfile.class | grep invoke and you'll have the binary signatures that the class "calls" from other classes. Yes, I know, it's not what you wanted but you could use it as a last resource.
If you need a more "javaish" solution, you could have a look at a java library called "asm": http://asm.ow2.org/
You could pass a dynamic proxy object to the caller, which inside checks the methods against your white list and throws exception when the call is not allowed.
Dynamic proxies basically allows you to insert piece of code between the caller's method invocation and the actual invocation of the called method.
I'd really think through though to if you really need this. Dynamic proxies are useful but they can also be very confusing and annoying to debug.
Given a java.lang.reflect.Method object, is there anyway to determine whether the method is purely functional (i.e., given the same input, it will always produce the same output and it is stateless. In other words, the function does not depend on its environment)?
No, there's no way to do it.
Reflection does not allow you to inspect the actual code behind the method.
And even if that where possible, the actual analysis would probably be ... tricky, to say the least.
No there is no way to do that with reflection or any other mechanism.
The developer knows if the method is functional. For example, Spring has a #Cacheable annotation that gives a hint to the application that the method is functional and can therefore cache the result for a given set of arguments. (Spring will wrap your object in a proxy that provides the caching behavior.)
is there anyway to determine whether the method is purely functional(ie., given the same input, it will always produce the same output
I know it's now what you've asked for, but Unit Tests may help you with this.
No. Reflection can not read the byte code of the method. So you can't really tell what a method does or even what other classes it uses.
Reflection will not help you here. If you really want to define it at run time, you can try to use javap -c classname.class. But it would be better to avoid such a hacks.
I want to replace calls to a given class with calls to anther class within a method body whilst parsing compiled class files...
or put another way, is there a method of detecting usages of a given class in a method and replacing just that part of the method using something like javaassist.
for example.. if I had the compiled version of
class A { public int m() { int i = 2; B.multiply(i,i); return i; } }
is there a method of detecting the use of B and then altering the code to perform
class A { public int m() { int i = 2; C.divide(i,i); return i; } }
I know the alternative would be to write a parser to grep the source files for usages but I would prefer a more elegant solution such as using reflection to generate new compiled class files.
Any thoughts ?
As #djna says, it is possible to modify bytecode files before you load them, but you probably do not want to do this:
The code that does the code modification is likely to be complex and hard to maintain.
The code that has been modified is likely to be difficult to debug. For a start, a source level debugger will show you source code that no longer corresponds to the code that you are actually editing.
Bytecode rewriting is useful in certain cases. For example, JDO implementations use bytecode rewriting to replace object member fetches with calls into the persistence libraries. However, if you have access to the source code for these files, you'll get a better (i.e. more maintainable) solution by preprocessing (or generating) the source code.
EDIT: and AOP or Groovy sound like viable alternatives too, depending on the extent of rewriting that you anticipate doing.
BCEL or ASM.
I recently looked at a number of libraries for reading Java class files. BCEL was the fastest, had the least number of dependencies, compiled out of the box, and had a deliciously simple API. I preferred BCEL to ASM because ASM has more dependencies (although the API is reputedly simpler).
AspectJ, as previously mentioned, is another viable option.
BCEL is truly simple. You can get a list of methods in three lines of code:
ClassParser cp = new ClassParser( "A.class" );
JavaClass jc = cp.parse();
Method[] m = jc.getMethods();
There are other API facilities for further introspection, including, I believe, ways to get the instructions in a method. However, this solution will likely be more laborious than AspectJ.
Another possibility is to change the multiply or divide methods themselves, rather than trying to change all instances of the code that calls the operation. That would be an easier road to take with BCEL (or ASM).
The format of byte code for compiled Java is specified and products exist that manipulate it.
This library appears to have the capability you need. I've no idea how easy it is to do these transformations reliably.
If you don't mind using Groovy, you can intercept the call to B.multiply and replace it with C.divide. You can find an example here.
It's much easier to perform these operations ahead-of-time, where the executable on disk is modified before launching the application. Manipulating the code in memory at run time is even more prone to errors than manipulating code in memory in C/C++. Why do you need to do this?