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.
Related
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
I wish to create a custom remote execution client for my app. The client may look something like this:
interface Client {
<T> T computeRemotely(Function<List<MyBigObject>, T> consumer)
}
and might be used like this:
Client client = new Client();
Integer remoteResult = client.computeRemotely(list -> {
Integer result = -1;
// do some computational work here.
return result;
});
This means I somehow need to take lambda from the client, send it to the server, run the function (passing in a real List<MyBigObject>) and send the result back.
It's worth noting that a restriction on using my client library is that you cannot use anything outside the JDK in that lambda and expect it to work (as the classes may not be on the classpath on the server)...but I would like them to be able to use any of the JDK classes to bring in their own data to the calculation.
Now I can't just serialize the Function<MyBigObject, T> lambda because it serializes like an inner client of whatever class the lambda exists in which will NOT be on the classpath on the server.
So I have been looking at ASM to see whether that could work. Given that I have never done byte code manipulation before, I just wanted to check that what I am saying sounds right:
I can use ASM to convert to read the class that the lambda sits in.
Using a Method Visitor, get the method bytes, send them to the server
Use ASM to create an instance from the bytes and execute it.
Given that the lambda is like an anonymous inner class, I am guessing I will have to do some sort of method renaming in there too..
Is this roughly correct or have I got completely the wrong end of the stick?
Note that lambdas can access all immutable values from their context. Thus, you'd need to either forbid accessing external values (which would severely limit the usefulness of your solution) or identify them and send representations of those values (which runs into the problem you mentioned; their implementation may be outside the server classpath).
So even if you send the method representation (for which you would not even need ASM; you could get the Resource directly from the classloader), it won't work for the general case.
Edit: Given your comment, it could work. You'd need to synthesize a class with
The context attributes as final fields
A constructor with arguments for all the fields (you will passed the deserialized values there on construction)
The lambda method — see this question for details
There is no point in analyzing the runtime generated classes of lambda expressions. They have a very simple structure which they reveal when being serialized. During Serialization they will get replaced by a SerializedLambda instance which contains all information you could ever gather, most notably:
The implemented interface
The target method that will be invoked
The captured values
The crucial point is the target method. For lambda expressions (unlike method references) the target method is a synthetic method that resides within the class which contains the lambda expression. That method is private, by the way, that’s why an attempt to replicate the class invoking that method is doomed to fail, special JVM interaction is required to make it possible to create such a class. But the important point is that you need the target method on the remote side to execute it, the lambda specific runtime class is irrelevant. If you have the target method, you can create the lambda instance without third party libraries.
Of course, you can use ASM to analyze the target method’s code to transfer it (and all dependencies) to the remote side, but note that this is no different from transferring arbitrary Function implementations; the fact that there is a layer of a runtime generated class created via lambda expression does not help you in any way.
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.
How can i get hold of the instantiating object from a constructor in java?
I want to store reference to the parent object for some GUI classes to simulate event bubbling - calling parents handlers - but i dont wanna change all the existing code.
Short answer: there isn't a way to do this in Java. (You can find out what class called you, but the long answer below applies there for the most part as well.)
Long answer: Code that magically behaves differently depending on where it's being invoked from is almost always a bad idea. It's confusing to whoever has to maintain your code, and it seriously hurts your ability to refactor. For example, suppose you realize that two of the places instantiating your object have basicaly the same logic, so you decide to factor out the common bits. Surprise! Now the code behaves differently because it's being instantiated from somewhere else. Just add the parameter and fix the callers. It'll save you time in the long run.
If you want to know the invoking class, then pass "this" as a parameter to the constructor.
Thing thing = new Thing(this);
Edit: A modern IDE allowing refactoring will make this very easy to do.
Intercepting method calls (including constructors) without changing a ton of existing code is one thing Aspect-oriented programming was made for.
Check out AspectJ for a start.
With AspectJ, you can define a "pointcut" that specifies that you want to intercept constructor calls for a certain object or set of objects (using wildcards if need be), and within the interception code ("advice"), you will be given method context, which includes information about the both the calling method and object.
You can even use AspectJ to add fields to your object's to store the parent reference without modifying their existing code (this is called "introduction").
Is there a Java equivalent for the __call of PHP?
It would make sense to me if that's not the case, because it would probably result in compiler errors.
From the PHP manual on magic methods:
__call() is triggered when invoking inaccessible methods in an object context.
This sort of dynamic method/attribute resolution which is common in dynamically typed languages such as PHP, Python and Ruby is not directly supported in the Java language.
The effect can be approximated using Dynamic Proxies which requires you to have an interface for which the implementation will be dynamically resolved. Third party libraries such as CGLIB allow similar things to be done with normal Java classes.
This API based, special case interception of method invocation is not as convenient as the direct, always on support you can get with __call in PHP or equivalent features in other dynamically typed languages (such as __getattr__ in Python). This difference is due the fundamentally different ways in which method dispatch is handled in the two types of languages.
No, there is not.
as other said, java doesn't support this.
it does have something called a proxy class which can intercept calls to known methods (rather than undefined methods as in php's __call()). a proxy can be created dynamically as a wrapper around any interface:
http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html#proxy
http://java.sun.com/j2se/1.4.2/docs/guide/reflection/proxy.html#examples
Foo foo = (Foo) DebugProxy.newInstance(new FooImpl());
foo.bar(null);
foo looks like a Foo, but all the calls are intercepted by FooImpl's invoke() method.
to create a truly de novo class at runtime with dynamic methods in its interface, you can essentially compile a class definition and use java's class loader to import it at runtime. a tool like apache's JCI or Arch4J can handle this for you. still, the class will only have those methods you specify.
No, Java doesn't have that feature. For one thing, I think it would make overloading pretty much impossible (some argue overloading is a bad idea anyway, but this isn't the right forum for that debate). Beyond that, I get the sense that the designers of Java just feel that the flexibility something like that (I know it from Perl where it's called AUTOLOAD) is outweighed by the guarantee that any code that compiles is only calling methods that actually exist (barring binary incompatibilities).
No, java is a compiled language and the compiler wants to make sure that every function you call actually exists.