So I'm using a third party library in a Play application (namely the Echo Nest Java API). There are some oversights in how some methods are exposed by the library, and I need to modify one method in particular, which involves using a constructor with default access.
I had initially thought that creating a class in the same package that extends the class that I need to modify would do the trick, but it seems Java's runtime package handling is thwarting that attempt (that is, since different classloaders are being used for the two different classes, their being in the same package is not enough). I have some notion of potentially modifying the classloader for either my subclass or the Echo Nest library, but have just about no idea how to go about doing that or whether there's a better solution available.
Any pointers in the right direction would be appreciated!
So it turns out the solution was to load the library class using Play's default classloader, set the constructor to be accessible, and then use newInstance() to instantiate the library class. Some code, in case any one else runs into a similar problem:
// Use the default application classloader to load the library class
Class artistClazz = Play.application().classloader().loadClass("com.echonest.api.v4.Artist");
// Get the package private constructor that we need
Constructor<Artist> constructor = artistClazz.getDeclaredConstructor(EchoNestAPI.class, Map.class);
// Make sure it's accessible to this class
constructor.setAccessible(true);
return constructor.newInstance(this, (Map) mq.getObject("artist"));
I'm not by any means convinced that this was the best or cleanest solution to this problem, but it minimally affected the code outside of this modified subclass so I'll probably stick to it for now.
Related
I have a library with several packages-
lets say
package a;
package b;
inside package a I have public a_class
inside package b I have public b_class
a_class uses b_class.
I need to generate a library from this , but I do not want the Client to see b_class.
The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class.
Is there another way to do so ? maybe using interfaces or some form of design pattern ??
If you reject to move the code to an individual, controlled server, all you can do is to hinder the client programmer when trying to use your APIs. Let's begin applying good practices to your design:
Let your packages organized as they are now.
For every class you want to "hide":
Make it non-public.
Extract its public API to a new, public interface:
public interface MyInterface {...}
Create a public factory class to get an object of that interface type.
public class MyFactory
{
public MyInterface createObject();
}
So far, you have now your packages loosely coupled, and the implementation classes are now private (as good practices preach, and you already said). Still, they are yet available through the interfaces and factories.
So, how can you avoid that "stranger" clients execute your private APIs? What comes next is a creative, a little complicated, yet valid solution, based on hindering the client programmers:
Modify your factory classes: Add to every factory method a new parameter:
public class MyFactory
{
public MyInterface createObject(Macguffin parameter);
}
So, what is Macguffin? It is a new interface you must define in your application, with at least one method:
public interface Macguffin
{
public String dummyMethod();
}
But do not provide any usable implementation of this interface. In every place of your code you need to provide a Macguffin object, create it through an anonymous class:
MyFactory.getObject(new Macguffin(){
public String dummyMethod(){
return "x";
}
});
Or, even more advanced, through a dynamic proxy object, so no ".class" file of this implementation would be found even if the client programmer dares to decompile the code.
What do you get from this? Basically is to dissuade the programmer from using a factory which requires an unknown, undocumented, ununderstandable object. The factory classes should just care not to receive a null object, and to invoke the dummy method and check the return value it is not null either (or, if you want a higher security level, add an undocumented secret-key-rule).
So this solution relies upon a subtle obfuscation of your API, to discourage the client programmer to use it directly. The more obscure the names of the Macguffin interface and its methods, the better.
I need to generate a library from this , but I do not want the Client to see b_class. The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class. Is there another way to do so ?
Yes, make b_class package-private (default access) and instantiate it via reflection for use in a_class.
Since you know the full class name, reflectively load the class:
Class<?> clz = Class.forName("b.b_class")
Find the constructor you want to invoke:
Constructor<?> con = clz.getDeclaredConstructor();
Allow yourself to invoke the constructor by making it accessible:
con.setAccessible(true);
Invoke the constructor to obtain your b_class instance:
Object o = con.newInstance();
Hurrah, now you have an instance of b_class. However, you can't call b_class's methods on an instance of Object, so you have two options:
Use reflection to invoke b_class's methods (not much fun, but easy enough and may be ok if you only have a few methods with few parameters).
Have b_class implement an interface that you don't mind the client seeing and cast your instance of b_class to that interface (reading between the lines I suspect you may already have such an interface?).
You'll definitely want to go with option 2 to minimise your pain unless it gets you back to square one again (polluting the namespace with types you don't want to expose the client to).
For full disclosure, two notes:
1) There is a (small) overhead to using reflection vs direct instantiation and invocation. If you cast to an interface you'll only pay the cost of reflection on the instantiation. In any case it likely isn't a problem unless you make hundreds of thousands of invocations in a tight loop.
2) There is nothing to stop a determined client from finding out the class name and doing the same thing, but if I understand your motivation correctly you just want expose a clean API, so this isn't really a worry.
When using Kotlin, you can use the internal modifier for your library classes.
If I understand correctly you are asking about publishing your library for 3rd party usage without disclosing part of your source? If that's the case you can use proguard, which can obfuscate your library. By default everything will be excluded/obfuscated, unless you specify things you want to exclude from being obfuscated/excluded.
If you want to distribute [part of] your code without the client being able to access it at all, that means that the client won't be able to execute it either. :-O
Thus, you just have one option: Put the sensible part of your code into a public server and distribute a proxy to access it, so that your code would be kept and executed into your server and the client would still be able to execute it through the proxy but without accessing it directly.
You might use a servlet, a webservice, a RMI object, or a simple TCP server, depending on the complexity level of your code.
This is the safest approach I can think of, but it also deserves a price to pay: In addition to complexing your system, it would introduce a network delay for each remote operation, which might be big deal depending on the performance requirements. Also, you should securize the server itself, to avoid hacker intrussions. This could be a good solution if you already have a server that you could take advantage of.
We have some portion of functionality packed in an external library and it is attached to our project. That library can't be changed in any way. Amongst others there are two classes lying inside it: com.myorg.Grandpa and com.myorg.Dad that extends com.myorg.Grandpa. Also there are com.myorg.Grandson extending com.myorg.Dad and a few other classes outside of the library extending com.myorg.Grandpa.
I decompile com.myorg.Grandpa class and add a new method new_method() to it.
Then I try to use new_method() in com.myorg.Grandson but IDEA won't let me do it cause Grandson extends Dad which extends library's Grandpa which doesn't contain new_method().
I tried to delete Grandpa from library and surprisingly IDEA didn't say a word and successfully compiled a project despite of the fact that in the boundaries of a library Dad extends non existing class.
The question is how to force Dad to extend a new Grandpa without deleting the one inside a library?
You could
Add an abstract class between Dad and GrandSon: Extend Dad, and add your method in the sub class. Then derive GrandSon from that sub class.
Put an instance of Dad in a new class, and let your IDE create delegate methods to the aggregated Dad instance. Again add your new method to the new class.
There is another possibility:
If you have to modify classes in place, use aspectj to weave in code: aspectj changes the byte-code (it does not need source code) at run-time. This way you can add methods or fields.
The fact is that you are duplicating classes with full package signature, so you will get the one that the classloader loads first. I know that in Websphere you can tweak classloader priorities, but couldn't say in your case.
Anyway, why not just do it without decompiling? You are causing yourself hard coupling to an external library and bad practices (maybe copyright issues) by decompiling/customizing. Besides, if the library gets updated, you will run into trouble having to reconstruct your customized classes.
Options:
Create your own implementation, for instance:
Create an Interface that replicates all methods in Grandpa plus the one you need.
Extend Grandpa class and implement the added method from your interface, all other methods will be left intact.
Extend all other extending classes from your own class hierarchie.
Instead of using the libraries common class, use your Interface as naming
This way you are kind of creating your own interface to the library, if it changes, you know where to make changes.
You could even do it without the interface, it's kind of wrapping the functionality, it would depend on what you need to achieve.
Anyway, I would try to solve it by own code and not by messing up with the library, it is just not worth it to do such tricks, if a new Programmer takes the project, they will need a lot of time to find out why and how it behaves.
Now, there might be variations in how to structure the class hierarchie, but it would depend on the specific implementation you need, so you would have to post more detailed data on what the library is and what you're trying to add to it if you expect some more specific answer...
Regards
It has to appear first to the class loader.
IDEA should load your class first if is in your project. You may also try to create a separate library for your class and include it in your project.
See also: http://www.jetbrains.com/idea/webhelp/configuring-module-dependencies-and-libraries.html
There is a library have a base class (let's call it CBase) that performs some tasks and one can create classes that extends this CBase class.
The behavior of the CBase is not enough for me, so I would like to create my own CBase class (let's call it MyCBase) that have the same methods and members but these methods don't do the same thing.
Until now everything is ok. But what blocks me is that I would like to replace CBase by MyCBase. However, I have a lot of classes that extend CBase and I don't want to change them all.
Is it possible to replace CBase by MyCBase at runtime ?
So that
public class A extends CBase {}
becomes
public class A extends MyCBase {}
Can I perform this using code enhancement ? (like we do to add methods to a class at runtime. Is it also possible to change inheritance this way ?)
Thank you for your help !
EDIT
I would like to write a plugin for a framework, this is why I would like to change inheritance at runtime. This way users of the framework can use my plugin without changing their source code (changing the inheritance of their classes from CBase to MyCBase)
EDIT 2
Is it possible to do like this: ?
CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();
I'm not expert. Probably you could extend ClassLoader. But I highly recommend don't do it. The replacement will touch many of your classes but it will be clear in code reading and app execution.
I think there is also room for architecture improvement since you have so many classes extend CBase. People are trying to remove dependencies from other libraries or keep it really small. Because in this case you could easily switch to another library or add your own functionality.
I dont think you can change the extends of a class at runtime. I would suggest to change the extends of the objects or build an interface, which contains all the things your need
Changing all derived classes is a simple matter, provided you control their source code:
Create a new class in your project. Call it CBase, and put it in the same package as the library class.
Use the rename/move refactoring of your IDE to rename CBase to MyBase. This will have the IDE rename all references to the renamed/moved class ...
Write the code for MyBase, extending from CBase.
If you can not do this (for instance because some derived classes are in a library you do not control), you replace the implementation of CBase with your own. Simply create a class of the same package and name in your project (the classloader searches the classpath in order, and uses the first class of the proper package and name it finds). This approach however is very brittle, as the compiler can not check binary compability between the old and new version of CBase. The JVM will check this compatibility when classes are loaded, but since classes are only loaded when needed, its hard to test your changes. (Which is why I do not recommend this approach if there are other options).
You could also change the classes as they are loaded my manipulating the class file, that that's going to be even more brittle, and the compiler would allow you to use any additional features MyBase might have. ==> Definitely not a good idea.
Is there a feasible way to get my own code run whenever any class is loaded in Java, without forcing the user explicitly and manually loading all classes with a custom classloader?
Without going too much into the details, whenever a class implementing a certain interface read its annotation that links it with another class, and give the pair to a third class.
Edit: Heck, I'll go to details: I'm doing an event handling library. What I'm doing is having the client code do their own Listener / Event pairs, which need to be registered with my library as a pair. (hm, that wasn't that long after all).
Further Edit: Currently the client code needs to register the pair of classes/interfaces manually, which works pretty well. My intent is to automate this away, and I thought that linking the two classes with annotations would help. Next, I want to get rid of the client code needing to keeping the list of registrations up to date always.
PS: The static block won't do, since my interface is bundled into a library, and the client code will create further interfaces. Thus, abstract classes won't do either, since it must be an interface.
If you want to base the behavior on an interface, you could use a static initializer in that interface.
public interface Foo{
static{
// do initializing here
}
}
I'm not saying it's good practice, but it will definitely initialize the first time one of the implementing classes is loaded.
Update: static blocks in interfaces are illegal. Use abstract classes instead!
Reference:
Initializers (Sun Java Tutorial)
But if I understand you right, you want the initialization to happen once per implementing class. That will be tricky. You definitely can't do that with an interface based solution. You could do it with an abstract base class that has a dynamic initializer (or constructor), that checks whether the requested mapping already exists and adds it if it doesn't, but doing such things in constructors is quite a hack.
I'd say you cleanest options are either to generate Code at build time (through annotation processing with apt or through bytecode analysis with a tool like asm) or to use an agent at class load time to dynamically create the mapping.
Ah, more input. Very good. So clients use your library and provide mappings based on annotations. Then I'd say your library should provide an initializer method, where client code can register classes. Something like this:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
Or, even better, a package scanning mechanism (example code to implement this can be found at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
Anyway, there is basically no way to avoid having your clients do that kind of work, because you can't control their build process nor their classloader for them (but you could of course provide guides for classloader or build configuration).
If you want some piece of code to be run on any class loading, you should:
overwrite the ClassLoader, adding your own custom code at the loadClass methods (don't forget forwarding to the parent ClassLoader after or before your custom code).
Define this custom ClassLoader as the default for your system (here you got how to do it: How to set my custom class loader to be the default?).
Run and check it.
Depending on what kind of environment you are, there are chances that not all the classes be loaded trouugh your custom ClassLoader (some utility packages use their own CL, some Java EE containers handle some spacific areas with specific classLoaders, etc.), but it's a kind of aproximation to what you are asking.
This question already has answers here:
How can I get a list of all the implementations of an interface programmatically in Java?
(11 answers)
Closed 9 years ago.
Some time ago, I came across a piece of code, that used some piece of standard Java functionality to locate the classes that implemented a given interface. I know the functions were hidden in some non-logical place, but they could be used for other classes as the package name implied. Back then I did not need it, so I forgot about it, but now I do, and I can't seem to find the functions again. Where can these functions be found?
Edit: I'm not looking for any IDE functions or anything, but rather something that can be executed within the Java application.
Awhile ago, I put together a package for doing what you want, and more. (I needed it for a utility I was writing). It uses the ASM library. You can use reflection, but ASM turned out to perform better.
I put my package in an open source library I have on my web site. The library is here: http://software.clapper.org/javautil/. You want to start with the with ClassFinder class.
The utility I wrote it for is an RSS reader that I still use every day, so the code does tend to get exercised. I use ClassFinder to support a plug-in API in the RSS reader; on startup, it looks in a couple directory trees for jars and class files containing classes that implement a certain interface. It's a lot faster than you might expect.
The library is BSD-licensed, so you can safely bundle it with your code. Source is available.
If that's useful to you, help yourself.
Update: If you're using Scala, you might find this library to be more Scala-friendly.
Spring can do this for you...
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(CLASS_YOU_WANT.class);
s.addIncludeFilter(tf);
s.scan("package.you.want1", "package.you.want2");
String[] beans = bdr.getBeanDefinitionNames();
N.B. The TypeFilter is important if you want the correct results!
You can also use exclusion filters here instead.
The Scanner can be found in the spring-context jar, the registry in spring-beans, the type filter is in spring-core.
I really like the reflections library for doing this.
It provides a lot of different types of scanners (getTypesAnnotatedWith, getSubTypesOf, etc), and it is dead simple to write or extend your own.
The code you are talking about sounds like ServiceLoader, which was introduced in Java 6 to support a feature that has been defined since Java 1.3 or earlier. For performance reasons, this is the recommended approach to find interface implementations at runtime; if you need support for this in an older version of Java, I hope that you'll find my implementation helpful.
There are a couple of implementations of this in earlier versions of Java, but in the Sun packages, not in the core API (I think there are some classes internal to ImageIO that do this). As the code is simple, I'd recommend providing your own implementation rather than relying on non-standard Sun code which is subject to change.
Package Level Annotations
I know this question has already been answered a long time ago but another solution to this problem is to use Package Level Annotations.
While its pretty hard to go find all the classes in the JVM its actually pretty easy to browse the package hierarchy.
Package[] ps = Package.getPackages();
for (Package p : ps) {
MyAno a = p.getAnnotation(MyAno.class)
// Recursively descend
}
Then just make your annotation have an argument of an array of Class.
Then in your package-info.java for a particular package put the MyAno.
I'll add more details (code) if people are interested but most probably get the idea.
MetaInf Service Loader
To add to #erickson answer you can also use the service loader approach. Kohsuke has an awesome way of generating the the required META-INF stuff you need for the service loader approach:
http://weblogs.java.net/blog/kohsuke/archive/2009/03/my_project_of_t.html
You could also use the Extensible Component Scanner (extcos: http://sf.net/projects/extcos) and search all classes implementing an interface like so:
Set<Class<? extends MyInterface>> classes = new HashSet<Class<? extends MyInterface>>();
ComponentScanner scanner = new ComponentScanner();
scanner.getClasses(new ComponentQuery() {
#Override
protected void query() {
select().
from("my.package1", "my.package2").
andStore(thoseImplementing(MyInterface.class).into(classes)).
returning(none());
}
});
This works for classes on the file system, within jars and even for those on the JBoss virtual file system. It's further designed to work within standalone applications as well as within any web or application container.
In full generality, this functionality is impossible. The Java ClassLoader mechanism guarantees only the ability to ask for a class with a specific name (including package), and the ClassLoader can supply a class, or it can state that it does not know that class.
Classes can be (and frequently are) loaded from remote servers, and they can even be constructed on the fly; it is not difficult at all to write a ClassLoader that returns a valid class that implements a given interface for any name you ask from it; a List of the classes that implement that interface would then be infinite in length.
In practice, the most common case is an URLClassLoader that looks for classes in a list of filesystem directories and JAR files. So what you need is to get the URLClassLoader, then iterate through those directories and archives, and for each class file you find in them, request the corresponding Class object and look through the return of its getInterfaces() method.
Obviously, Class.isAssignableFrom() tells you whether an individual class implements the given interface. So then the problem is getting the list of classes to test.
As far as I'm aware, there's no direct way from Java to ask the class loader for "the list of classes that you could potentially load". So you'll have to do this yourself by iterating through the visible jars, calling Class.forName() to load the class, then testing it.
However, it's a little easier if you just want to know classes implementing the given interface from those that have actually been loaded:
via the Java Instrumentation framework, you can call Instrumentation.getAllLoadedClasses()
via reflection, you can query the ClassLoader.classes field of a given ClassLoader.
If you use the instrumentation technique, then (as explained in the link) what happens is that your "agent" class is called essentially when the JVM starts up, and passed an Instrumentation object. At that point, you probably want to "save it for later" in a static field, and then have your main application code call it later on to get the list of loaded classes.
If you were asking from the perspective of working this out with a running program then you need to look to the java.lang.* package. If you get a Class object, you can use the isAssignableFrom method to check if it is an interface of another Class.
There isn't a simple built in way of searching for these, tools like Eclipse build an index of this information.
If you don't have a specific list of Class objects to test you can look to the ClassLoader object, use the getPackages() method and build your own package hierarchy iterator.
Just a warning though that these methods and classes can be quite slow.