How can I conveniently wrap a caller-sensitive API? - java

Certain Java APIs are caller-sensitive. One (woefully underdocumented IMO) example is System.load(), which loads some JNI code into the caller's ClassLoader only.
I have a wrapper that looks roughly like JniUtils.loadLibrary("nameoflibrary"). It finds the appropriate library for the current architecture, extracts it out of the JAR, and passes it to System.load(). But I just ran into a case where the caller of JniUtils.loadLibrary wasn't in the same ClassLoader as Jni itself. That caused the library to get loaded into the wrong ClassLoader, resulting in UnsatisfiedLinkError once the native methods got called.
Without relying on JVM internals like sun.reflect.Reflection.getCallerClass(), is there a way to work around this issue? My current idea is to change the wrapper like this:
public class JniUtils {
public static void loadLibrary(String libraryName, MethodHandles.Lookup lookup);
}
which can be called like this:
public class NeedsJni {
static {
JniUtils.loadLibrary("nameoflibrary", MethodHandles.lookup());
}
}
Using the Lookup to resolve and call the System.load() method should preserve NeedsJni as the caller.
Is there a better workaround?

Depending on the complexity of your problem, this may or may not be applicable.
Under a context without reflection, it's hard for standard java code to replicate caller-sensitivity, even more so to "emulate" it to a caller-sensitive function. Even if it were done the code, in my opinion, would be incredibly obscure or would deal with deep dark language features that I would consider unnecessary.
The fundamental problem you have here is that System.load() is caller sensitive and you're trying to build your own "enhanced" System.load() by doing a bunch of other tasks prior to calling System.load() yourself. Why not leave System.load() exactly where it was when you started?
Rather than trying to replace the functionality of System.load(), complement it with your JniUtils class. Write a JniUtils.fetchLibrary() which returns a string in which the original caller can load from. Even better, return a custom object Library (or other names to that equivalent) containing a method that allows the retrieval of the string that should be passed to System.load(). From this, the call to load() can come from the point of need whilst your caller-insensitive code can do all the initialization separately.
Something to this example would be good:
public class JniUtils {
private static final HashMap<String, JniLibrary> cachedLibs = new HashMap<>();
public static JniLibrary fetchLibrary(String libname){
// Check cache for library
if(cachedLibs.containsKey(libname)){
return cachedLibs.get(libname);
}else{
JniLibrary lib = preloadLibrary(libname);
if(lib != null){
cachedLibs.put(libname, lib);
}
return lib;
}
}
/**
* Internal logic to prepare and generate a library instance
*
* #return JNI library on success, null on failure.
*/
private static JniLibrary preloadLibrary(String libname){
// Find lib
// Extract
// Get path
// Construct JniLibrary instance
// Return library as appropriate
}
/**
* Class representing a loadable JniLibrary
*/
public class JniLibrary{
public String getLibraryPath();
// Other potentially useful methods
}
}
public class NeedsJni {
static {
JniLibrary lib = JniUtils.fetchLibrary("nameoflibrary");
if(lib != null){
System.load(lib.getLibraryPath()); // Caller-sensitivity respected
}else{
// Well.... this is awkward.
}
}
}
not only does that solve the caller-sensitivity issue, the additional caching prevents additional extraction/architecture lookup and eventual failure (since the file you extract to would probably have been in use), allowing multiple calls to System.load() from different classes under different classloaders as appropriate.
The countercase to this approach is that if there is important code that has to be executed right after System.load() in your custom loadLibrary() method (suddenly, you wished java would have some sort of "OnLibraryLoad" event). In that case, perhaps add a method to run the post-load code within your main JniUtils class or the returned Library class (it's more ugly I know, but with clear documentation, it can't be that bad).

Consider defining an abstract class which has to be provided if the classpath is going to be incompatible. This provides "caller sensitivity" as the caller has to provide the implementation, thus providing the necessary context.
public class JniUtils {
public static void loadLibrary(String libraryName, Delegate delegate) {
//use delegate's provided classloader to find the native library from within the jar and extract
//ask the delegate to load the extracted library
}
public static abstract class Delegate {
/**
* #return The specific ClassLoader instance to use to find the native resource. If returning null, the ClassLoader of JniUtils will be used.
*/
public ClassLoader getLibraryClassLoader() {
return getClass().getClassLoader();
}
/**
* <p>
* The callback method which will be called once the native library's name has been
* resolved. This MUST be implemented by the subclass, so that it resolves as the "caller"
* class for {#link System#loadLibrary(String)}.
* </p>
*
* #param libraryName The name of the library to load.
*/
public abstract void loadLibrary(String libraryName);
}
}

Related

Java Application return super class when initialized

Nowadays we are on writing some core application that is all other application will be relying on. Without further due let me explain the logic with some codes,
We used to have a single java file that was 1000+ lines long and each application was having it as class inside, so when there was a change, each application had to edit the java file inside of it or simply fix one and copy to all. This is hard to implement as much as it is hard to maintain. Then we end-up with creating this as a separate application that is divided to smaller part, which is easy to maintain and also a core maybe a dependency to other application so we fix in one place and all other code applications are fixed too.
I've been thinking for a some great structure for this for a while want to use a builder patter for this as below
TheCore theCore = new TheCore().Builder()
.setSomething("params")
.setSomethingElse(true)
.build();
The problem arises now. Like so, I initialized the object but now I'm having access to that objects public class only. This application actually will have many small classes that has public functions that I don't want them to be static methods that can be called everytime. Instead I want those methods to be called only if TheCore class is initilized like;
// doSomething() will be from another class
theCore.doSomething()
There are some ideas I produced like
someOtherClass.doSomething(theCore)
which is injecting the main object as a parameter but still someOtherClass needs to be initialized or even a static method which doesn't make me feel comfortable and right way to that.
Actually I do not care if initializing TheCore would bring me a super object that includes all other classes inside initialized and ready to be accessed after I initialized TheCore. All I want in this structure to have a maintainable separate app and methods avaiable if only the main object which is TheCore is this circumstances is initialized.
What is to right way to achive it? I see that Java does not allow extending multiple classes even it if does, I'm not sure it that is right way...
Thanks.
After spending significant amount of time of thought I ended up that
// doSomething() will be from another class
theCore.doSomething()
is not suitable since many java classes could possibly have identical method names. So...
// doSomething() will be from another class
theCore.someOtherClass.doSomething()
would be a better approach.
To make it easier to understand I'll have to follow a complex path to explain it which is starting from the package classes first.
Think that I have a package named Tools and a class inside SomeFancyTool
main
└─java
└─com
└─<domainName>
├─Tools
| └─SomeFancyTool.java
└─TheCore.java
Now this SomeFancyTool.java must have a default access level which is actually package level access, because I don't want this classes to be accessed directly;
SomeFancyTool.java
package com.<domainName>.Tools
class SomeFancyTool{
public String someStringMethod(){
return "Some string!";
}
public int someIntMethod(){
return 123;
}
public boolean someBooleanMethod(){
return true;
}
}
So now we have the SomeFancyTool.java class but TheCore.java cannot access it since it is accesible through its Tools package only. At this point I think of an Initializer class that is gonna be in the same package, initialize these private classes and return them with a function when called. So initiliazer class would look like this;
ToolsInitializer.java
package com.<domainName>.Tools
public class ToolsInitializer{
private SomeFancyTool someFancyTool = new SomeFancyTool();
public SomeFancyTool getSomeFancyTool(){
return someFancyTool;
}
}
Since ToolsInitializer.java can initialize all functional private classes inside in Tools package and also can return them as objects to outside of the package scope, still we are not able to use these methods as we cannot import com.<domainName>.SomeFancyTool from TheCore.java because it is package wide accessible. I think here we can benefit from implementation of the java interface. A class that is not functional alone, so no problem even if it is accessed since it's methods will be nothing but declarations.
At this point I'll rename SomeFancyTool.java to SomeFancyToolImplementation.java which it will be implementing the interface and call SomeFancyTool.java to the interface itself.
SomeFancyTool.java (now as an interface)
package com.<domainName>.Tools
public interface SomeFancyTool{
public String someStringMethod();
public int someIntMethod();
public boolean someBooleanMethod();
}
and lets rename prior SomeFancyTool.java and implement the interface
SomeFancyToolImplementation.java (renamed)
package com.<domainName>.Tools
class SomeFancyToolImplementation implements SomeFancyTool{
#override
public String someStringMethod(){
return "Some string!";
}
#override
public int someIntMethod(){
return 123;
}
#override
public boolean someBooleanMethod(){
return true;
}
}
Now our structure has become like this with the final edits;
main
└─java
└─com
└─<domainName>
├─Tools
| ├─SomeFancyTool.java
| ├─SomeFancyToolImplementation.java
| └─ToolsInitializer.java
└─TheCore.java
Finally we can use our TheCore.java class to call all initializer classes with their methods to receive all these private classes inside as an object. This will allow external apps to call and initialize TheCore first to be able to access other methods.
TheCore.java
public class TheCore{
private SomeFancyToolImplementation someFancyTool;
public static class Builder{
private SomeFancyToolImplementation someFancyTool;
public Builder(){
ToolsInitializer toolsInitializer = new ToolsInitializer();
someFancyTool = toolsInitializer.getSomeFancyTool();
}
public Builder setSomeValues(){
//some values that is needed.
return this;
}
public Builder setSomeMoreValues(){
//some values that is needed.
return this;
}
public TheCore build(){
TheCore theCore = new TheCore();
theCore.someFancyTool = someFancyTool;
return theCore;
}
}
}
All Done and it is ready to use. Now the functional package classes and its methods that it relying on if TheCore is initialized or not, cannot be accessed with out TheCore. And simple usage of this Library from a 3rd Party app would simply be;
3rd Party App
TheCore theCore = new TheCore.Builder()
.setSomeValues("Some Values")
.setMoreSomeValues("Some More Values")
.build();
theCore.someFancyTool.someStringMethod();
Note: Note that a the ToolsInitializer.java is still accessible and could be used the get private method without first calling TheCore but we can always set a checker inside getSomeFancyTool() method to throw error if some prerequisites are not satisfied.
I do not still know if this is a functional structural pattern to use or its just some hard thoughts of mine. And don't know if some pattern is already exist that I just could not see yet but this is the solution I end up with.

How is this interface being instantiated?

This is from the Minecraft server source code, also called the Minecraft Bukkit API, now you know as much as I do.
There is an interface called Server:
public interface Server extends PluginMessegeRecipient {
public String getVersion();
}
PluginMessageRecipient is an interface also.
There is a class called Bukkit that instantiates Server:
public final class Bukkit {
private static Server server;
}
Inside methods in the Bucket class they invoke methods from the server object. For example:
server.getVersion();
The thing is, there is no code for getVersion in the Server interface, just a method signature. There is also no code in the PluginMessageRecipient interface nor does it extend anything.
I have read all the questions and answers on SO that say I need an anonymous class or an inner class and this does not seem to fit those solutions.
There is a class called Bucket that instantiates Server:
Actually Bucket doesn't instantiate Server. The class Bucket contains a reference to a Server. You haven't shown how that got set so we don't know the actual class.
However, it is guaranteed that what is assigned to that reference (Bucket.server), assuming it's not null, is a an object of some concrete class that implements Server. That class will provide an implementation of getVersion() and that is what is being called.
Bukkit is just a Modding API. If you want to implement Bukkit, you need to create such an instance yourself and pass it there.
Take for example the unit tests that Bukkit includes:
https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/test/java/org/bukkit/TestServer.java#L77
A real implementation that allows you to run a Bukkit server is Spigot.
If I recall correctly, the particular concrete class that's being selected is determined at runtime via reflection. Because Minecraft is not open source, all the developers have are the obfuscated compiled class files to work with.
The code searches through each class file within the minecraft jar, searching for a class that matches certain conditions, and then, using a bytecode library, force that class to implement that interface.
For example, let's say that the following (obfuscated) class was the real Server class within the Minecraft code
class a {
String x_x317() {
return q_q98;
}
static a a_a1;
static String q_q98 = "1.9.4";
}
In this case, the method x_x317 returns the version string. The tool that allows them too hook into this class might do it based on the following conditions:
The class has default access
The class has only one default access static reference to itself
The class has only one default access static String field.
The class has a single method, that has default access, that returns String, and the returned value is the FieldRef found in 3.
This generally returns only one class. In the case that multiple are returned (usually in the dev phase of the new Bukkit version), they get more specific with their conditions to ensure that they only get the right class returned. They do this for every field, class, and method they need to identify.
Since they now know which exact class is the Server class, they can go ahead and make changes to it. First they would need to implement the interface
class a implements org.bukkit.Server
And then implement the method
class a implements org.bukkit.Server {
String x_x317() {
return q_q98;
}
public String getVersionNumber() {
return x_x317();
}
static a a_a1;
static String q_q98 = "1.9.4";
}
Now, we have a class that conforms to the Bukkit API.
When they need to instantiate that class, they just do something along the lines of
Server server = findAndTransformServerClassFromMinecraftJar();
// ...
Server findAndTransformServerClassFromMinecraftJar() {
// load classes from jar
// map them to the appropriate interfaces
// transform and hook the required classes and methods
Class<?> serverClass = doTheFirstThreeSteps();
return (Server) serverClass.newInstance();
}

How to "proxy" a method in Java

First off, I'm not sure how to best word my solution so if I seem to be babbling at times then please consider this.
There is an interface in a library I wish to modify without touching the physical code,
public interface ProxiedPlayer {
// .. other code
public void setPermission(String permission, boolean state);
}
I have written a third party library for handling permissions and having to hook into my API to edit permissions may be a step some developers do not want to take. So I ask that when setPermission is called is it possible to have it invoke my invoke the appropriate method in my library that will handle permission setting whilst ignoring the pre-programmed code or not?
Here is the full interface I am attempting to proxy.
I have looked into the Java Proxy class but it seems you need an instance of the object you're trying to proxy in the first place. Given that the method can be called any time I do not believe this to be my solution but will happily stand corrected.
I do not have control over instantiation of classes implementing the ProxiedPlayer interface.
EDIT: Ignorant me, there several events that I can subscribe to where it is possible to get an instance of the player, would this be the appropriate place to attempt to proxy the method? One of these events is fired when a player joins the server and getting the instance of the player is possible.
Would the Proxy code need to be called for every instance of the ProxiedPlayer interface or is it possible to simply proxy every invocation of the method in an easier way?
My library is a plugin loaded after everything else that is essential has finished loading.
Edit #2:
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationProxy implements InvocationHandler {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ProxiedPlayer player = (ProxiedPlayer) proxy;
if(method.getName().equals("setPermission")) {
// Call my code here?
}
return method.invoke(player, args);
}
}
Would something along the lines of what I have above work or am I barking up the wrong tree entirely?
If you do not want to touch the original source, then you only solve this problem by using a Java agent that redefines any class that implements the ProxiedPlayer interface to enforce your security check before calling the actual method. AspectJ together with a load-time-weaving agent was already mentioned as a possible solution for this but you can also implement a pure Java solution using my library Byte Buddy:
public class InterceptionAgent {
public static void premain(String arguments,
Instrumentation instrumentation) {
new AgentBuilder.Default()
.rebase(isSubtypeOf(ProxiedPlayer.class))
.transform(new AgentBuilder.Transformer() {
#Override
public DynamicType.Builder transform(DynamicType.Builder builder) {
return builder.method(named("setPermission"))
.intercept(MethodDelegation.to(MyInterceptor.class)
.andThen(SuperMethodInvocation.INSTANCE));
}
}).installOn(instrumentation);
}
}
With this agent, you more or less specify that you want to redefine any class that is a subtype of ProxiedPlayer to redefine (any) method named setPermisson in order to call a MyInterceptor (that would be your code) and to subsequently call the original implementation.
Note that the suggested implementation assumes that all classes implementing ProxiedPlayer implement the method of this interface and that there is only a single method of this signature. This might be too simple but it shows what direction to go.

How to reload a class so that a annotation becomes visible?

In a question I asked earlier I got to know that in order to really be sure that some annotation is present or not somewhere in a class I need to reload it with a classloader that has access to both - the annotation and the class.
Now I'm struggling with how such a classloader would work. In my setup I just have the annotation as a java.lang.Class instance and the class that might be annotated with that annotation also as a java.lang.Class instance. Both might be loaded by some different classloaders I don't know anything about (classes might be loaded remotely, so they are not on the local file system).
While searching I found this JoinClassLoader
/**
* A class loader that combines multiple class loaders into one.<br>
* The classes loaded by this class loader are associated with this class loader,
* i.e. Class.getClassLoader() points to this class loader.
* <p>
* Author Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland, www.source-code.biz<br>
* License: LGPL, http://www.gnu.org/licenses/lgpl.html<br>
* Please contact the author if you need another license.
*/
public class JoinClassLoader extends ClassLoader {
private ClassLoader[] delegateClassLoaders;
public JoinClassLoader (ClassLoader parent, ClassLoader... delegateClassLoaders) {
super (parent);
this.delegateClassLoaders = delegateClassLoaders; }
protected Class<?> findClass (String name) throws ClassNotFoundException {
// It would be easier to call the loadClass() methods of the delegateClassLoaders
// here, but we have to load the class from the byte code ourselves, because we
// need it to be associated with our class loader.
String path = name.replace('.', '/') + ".class";
URL url = findResource(path);
if (url == null) {
throw new ClassNotFoundException (name); }
ByteBuffer byteCode;
try {
byteCode = loadResource(url); }
catch (IOException e) {
throw new ClassNotFoundException (name, e); }
return defineClass(name, byteCode, null); }
// some code omitted
} // end class JoinClassLoader
So my question is this:
Given a class instance of an arbitrary class C and a class instance of an annotation class A that may be loaded by arbitrary classloaders. A JoinClassLoader is instantiated with the classloaders of C and A in this order as delegating classloaders. Will that JoinClassLoader reload class C upon invoking findClass so that annotation A is always visible when C was actually annotated with it? If not how would such a classloader actually look like?
In a question I asked earlier I got to know that in order to really be
sure that some annotation is present or not somewhere in a class I
need to reload it with a classloader that has access to both - the
annotation and the class.
Given a class that has already been loaded by a classloader which might not have had access to all the annotations, I can believe that to be true. I think you've drawn the wrong conclusion, however.
If you want to be able to reflectively analyze a class's annotations at runtime, then the best solution is not to reload it. Instead, you should ensure that it is loaded in the first place by a classloader that can also see the annotations of interest. (And if that turns out not to be sufficient, then I don't see how you can expect reloading to help.)
In any case, reloading the class gives you a different class (of the same name), even if its bytecode is identical to that of the previously-loaded version. It is tricky to use this for anything but reflective analysis, and it is very difficult to be certain that the two classes actually do have identical bytecode. Reloading certainly does not replace the existing class with the newly-loaded one. All manner of fun can ensue.

How to implement the API/SPI Pattern in Java?

I am creating a framework that exposes an API for developers to use:
public interface MyAPI {
public void doSomeStuff();
public int getWidgets(boolean hasRun);
}
All the developers should have to do is code their projects against these API methods. I also want them to be able to place different "drivers"/"API bindings" on the runtime classpath (the same way JDBC or SLF4J work) and have the API method calls (doSomeStuff(), etc.) operate on different 3rd party resources (files, servers, whatever). Thus the same code and API calls will map to operations on different resources depending on what driver/binding the runtime classpath sees (i.e. myapi-ftp, myapi-ssh, myapi-teleportation).
How do I write (and package) an SPI that allows for such runtime binding, and then maps MyAPI calls to the correct (concrete) implementation? In other words, if myapi-ftp allows you to getWidgets(boolean) from an FTP server, how would I could this up (to make use of both the API and SPI)?
Bonus points for concrete, working Java code example! Thanks in advance!
Take a look at the java.util.ServiceLoader class.
In general, the idea is this:
API Jar
Supply the interface
Use the ServiceLoader class to lookup the implementation
Binding/Driver Jar
Implement the interface
Create the file META-INF/ and specify the classname that implements it
There's a good example right in the javadocs:
http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
API Jar
package com.foo;
public interface FooInterface { ... }
public class FooInterfaceFactory {
public static FooInterface newFooInstance() {
ServiceLoader<FooInterface> loader = ServiceLoader.load(FooInterface.class);
Iterator<FooInterface> it = loader.iterator();
// pick one of the provided implementations and return it.
}
Binding Jar
package com.myfoo;
public class MyFooImpl implements FooInterface { ... }
META-INF/com.foo.FooInterface
com.myfoo.MyFooImpl
EDIT
SPI Example
public interface FooSpi {
void accepts(String url);
FooInterface getFooInstance();
}
public class FooInterfaceFactory {
public static FooInterface getFooInterfaceInstance(String url) {
ServiceLoader<FooSpi> loader = ServiceLoader.load(FooSpi.class);
Iterator<FooSpi> it = loader.iterator();
while (it.hasNext()) {
FooSpi fooSpi = it.next();
if (fooSpi .accepts(url)) {
return fooSpi.getFooInstance();
}
}
return null;
}
}
And of course, change the filename to com.foo.FooSpi and provide an implementation of FooSpi. That will allow you to segregate the public API from the Spi interface.
If you want to hide the accepts method, you could always have a second interface which is your public API, and t
Well you know that API are what clients use, and SPI is what your library use internally.
You shall have classes which implement your API classes, which depend on SPI interfaces, and have some implementations for your SPI.
Most of the time SPI interfaces contain low level methods (abstraction for direct working with FTP, SSH and... in your example), and your library provides higher level operations for your clients.
Maybe your SPI interfaces would be such as:
public interface ProtocolSPI {
boolean isCompatibleWithUrl(String url);
Handle connect(String url, Map<String, Object> parameters);
int readData(Handle handle, byte[] bytes);
void writeData(Handle handle, byte[] bytes, int startIndex, int length);
void closeHandle(Handle handle);
}
and you have code which depends on this interface for working with replaceable part.
You may have a ProtocolSPIFactory which uses java.util.ServiceLoader to find available implementations of your ProtocolSPI (in the class-path), then instantiates them and by calling isCompatibleWithUrl finds out which implementation to use for a specific url.

Categories

Resources