I have a library that I'm using in an Java application - it's important for certain functionality, but it's optional. Meaning that if the JAR file is not there, the program continues on without issue. I'd like to open source my program, but I can not include this library, which is necessary to compile the source code as I have numerous import statements to use the API. I don't want to maintain two code sets. What is the best way to remove the physical jar file from open source release, but still maintain the code to support it where other people could still compile it?
the typical approach taken is to define the wrapper API (i.e. interfaces) and include those interfaces in the open sourced code, and then provide configuration options where one can specify class names of classes that implement certain interfaces.
You will import API interfaces instead of importing classes directly into your open sourced code. This way, you are open sourcing the API but not the implementation of the parts that you do not want to open source or you cannot open source.
There are many examples, but take a look at JDBC API (interfaces) and JDBC drivers (implementation classes) for starters.
I was pretty much typing the same thing as smallworld with one addition. If this API were necessary you can use a project build tool like Maven to handle the dependencies on you project. If someone checks it out from source control with the pom they can download the dependencies for themselves and you don't have to include them in a source repo.
There's probably a number of ways to fix this, here's a couple I can think of:
If you have only a couple of methods you need to invoke in the 3rd party library, you could use reflection to invoke those methods. It creates really verbose code, that is hard to read though.
If you don't have too much of the API in the 3rd party library you use, you could also create a separate JAR file, containing just a non-functional shell of the classes in the library (just types with the same names and methods with the same signatures). You can then use this JAR to distribute and compile against. At run-time you'd replace it with the real JAR if available.
The most common way is probably to just create a wrapper API in a separate module/project for the code that is dependent on the 3rd party library, and possibly distribute a pre-built JAR. This might go against your wish to not maintain two code sets, but may prove to be the best and less painful solution in the long run.
Related
I've got a large Java library and I want to develop several smaller applications that interface this library. The library will be present on the target device's class-path as JAR, but I would like to avoid the need to have the entire library (either JAR or source) present at compile-time if possible. (If it matters, the JAR is quite huge and I want to protect intellectual property too, though it's not my primary concern.)
In C++, I would solve this issue by creating a DLL (.so) and copying just the relevant class and function definition headers to my project and adding them to include path at compile time, let the dynamic linker do the job at runtime.
How to do this in Java? One idea I have would be to remove private methods/members, and strip methods of relevant classes so that their bodies are empty and the real classes and methods with same signatures are loaded at runtime. However, this approach seems quite ugly and rudimental, plus some tool would be needed to automate this process. Is there a tool to do this? Is there a better way?
I don't think it's a duplicate of this question. The point of that question is to minimize size of the resulting JAR file at compile time, by removing unnecessary classes. My point is not to remove unused definitions, but to avoid the need of having the complete library JAR at compile time at all. Though these are simmilar and there may be a way how to achieve what I want using ProGuard, the linked question does not discuss it.
There's no exact equivalent for header files in Java, but compiling against the "header" (in the meaning of "contract") without having the actual implementation can be achieved using interfaces:
Create interface for every class you want the "header" for, with relevant methods
Make the actual classes implement the respective interfaces
Pack the interfaces into one JAR, and the implementations into another one
(if you're using a build tool like Maven, use two projects, and let the implementation project depend on the interface one)
Only provide the interface JAR at compile time, and both at run time
There of course will need to be some artifact that knows the actual implementations and can instantiate them, or you'll have to use some lookup that searches classpath for a suitable implementation.
If your problem is only due to the minimization of the final jar and you use Apache Maven, you could try to use the option "provided" when you declare a dependency in the pom.xml.
For example I use this dependency declaration:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.48</version>
<scope>provided</scope>
</dependency>
This means that my java compiler use the bouncycastle library to compile, but finally it doesn't include it in the final jar. You should provide it during execution.
I have a game written in Java and a whish to write a generic ModLoader/AddonLoader application. A separate application/api that would allow you to create mods/addons for my projects that add extra implementation that I do not want in the main application.
However I am not sure how to go about this, i've done some research and im not too sure how to make the mod/addon interact with a loader which interacts with the main application to add new features/modify old
Many Thanks
Elliott
Since you're looking for some basic guidance I'll suggest the following:
You need a way to pull in classes after the core application is running. That means you will need these classes on the classpath. The simplest way to do that is probably to have your classpath include a folder like "addons" so that all the jars in that folder are automatically on your application's classpath.
Once you have your classpath set up you will need to somehow make use of the appropriate class(es). This part is hard to speak generically about because it depends heavily on how you intend your addons to work. Some tools use annotations to help with this and you can probably look at some open source projects for examples. One that comes to mind is Maven, it makes use of annotations in its plugin system. The general concept is that you need to decide how many different kinds of addons you have and how you will identify them and make use of them.
Typically making use of an addon involves instantiating that addon which is why it can be tricky. Some plugin systems require that addons be written such that they use a specific package name. They do this so that they can make use of reflection to find all classes in a given package and then process them.
Hope that helps to get you started!
We are having a discussion at work and an interesting point came up:
Say you are developing a small library, call it somelib. Say that somelib needs to do some logging, but you don't want to reinvent the wheel, so you decide to use a 3rd party logging library.
Additionally, you want to make integration of somelib as painless as possible, so you distribute a single JAR file (somelib.jar), which has the other logging JAR, call it logger.jar, embedded inside of it. Much like what Maven's jar-with-dependencies assembly does.
Now comes the issue. Since your product is a library, what if your customer is using somelib and also happen to be using a different version of the same logging library on their own. Now we have a classpath problem.
This seems to me like it would be a common problem for people that write libraries, so what is the typical solution?
Do they avoid using JAR bundling methods altogether? Even if we do that, there is still an issue with a user's code expecting version X of the logging library, and somelib's code expecting version Y.
Do they somehow insert a dummy package prefix so that the logger classes in somelib won't conflict?
What about dynamic loading of the logger library? (though this still has versioning problems from 1.)
You may consider to use OSGI or wait for JDK 8 and its Jigsaw project.
I created a program in Java and I designed it so that methods that I want them to appear (getter methods) in the main, I can call them easily after initiate the class that holds these methods.
The question is that, I need to make this application (that holds the getter methods) to be like an API so that I can give my application for developers to use my functions (the getter methods) if they need them, and only what they need is to add this file (I think the API after is done shown as .jar file).
How can I make it so that I can make my code reusable with other application? It's similar to the .dll, I think.
Thanks a lot ;)
Create a JAR. Then include the JAR. Any classes in that JAR will be available. Just make sure you protect your code if you are giving out an API. Don't expose any methods / properties to the end user that shouldn't be used.
Edit: In response to your comment, make sure you don't include the source when you package the JAR. Only include the class files. That's the best you can really do.
To be useable as an API, your classes should:
Use a unique package (ideally following the convention, i.e. the reverse of a domain you own as prefix). This prevents naming conflicts
Have only those classes and methods public or protected that are intended to be used by others. This makes it easier to use.
Have extensive Javadoc comments.
Be available as a JAR file - ideally separate JARs for binary distribution, source code and javadoc files.
You need to package your application as a jar file. You can use ant jar task to create jar files or you can use the jar command.
For ant tasks look at this link.
For creating it manually look at this link.
Make sure you write and publish javadocs for all your public and protected classes and methods.
To create the jar:
jar cf <jar_name> <sources>
There are several ways you can expose your code. Creating a jar and distributing that may be the easiest as other developers will just have to include your jar. However, if you are talking about "anyone" accessing your code, a web service may make more sense as you can provide access to the data without providing all of the necessary code. You mention providing access to your getters - if you just create a class that has getters, the other developers can use them, but how are they going to be populated? If your application is self contained in that it gets the necessary data and provides the getters, that should work, but if you are talking about providing access to data from your running application, a web service makes more sense as your application can retrieve the data and provide access via publicly accessible methods.
You most likely want to create interfaces as well so developers can code against the interface and you can change the internal workings without impacting them. Any API that will be used by others should be extensively documented as well.
Well, depends on your IDE. I use Netbeans, so I just hit build project, and viola! A jar file is created in my directory specified. Now, that's just for compiling. All anyone has to do is download your .jar file, and if in Netbeans, right click libraries, add jar/folder, and select the downloaded file.
You can also consider:
Include some samples that demonstrate how to use your library
Build your jar using Apache Maven
Put your jar in a public maven repository
Publish a new version of your library as you find/fix bugs
If you want to hide your implementation, you can pack your jar with obfuscation, so that if someone decompiles your classes, the code will be difficult to read
It may not be best practice but are there ways of removing unsused classes from a third party's jar files. Something that looks at the way in which my classes are using the library and does some kind of coverage analysis, then spits out another jar with all of the untouched classes removed.
Obviously there are issues with this. Specifically, the usage scenario I put it though may not use all classes all the time.
But neglecting these problems, can it be done in principle?
There is a way.
The JarJar project does this AFAIR. The first goal of the JarJar project is to allow one to embed third party libraries in your own jar, changing the package structure if necessary. Doing so it can strip out the classes that are not needed.
Check it out at http://code.google.com/p/jarjar/.
Here is a link about shrinking jars: http://sixlegs.com/blog/java/jarjar-keep.html
There is a tool in Ant called a classfileset. You specify the list of root classes that you know you need, and then the classfileset recursively analyzes their code to find all dependencies.
Alternatively, you could develop a good test suite that exercises all of the functions that you need, then run your tests under a test coverage tool. The tool will tell you which classes (and statement in them) were actually utilized. This could give you an even smaller set of code than what you'd find with static analysis.
I use ProGuard for this. As well as being an excellent obfuscator, it has a code shrinking phase which can combine multiple JARs and then strip out any unused classes or class members. It does an excellent job at shrinking.
At a previous job, I used a Java obfuscator that as well as obfuscating the code, also removed classes and methods that weren't being used. If you were doing "Class.byName" or any other type of reflection stuff, you needed to tell the obfuscator because it couldn't tell by inspecting the code what classes or methods called by reflection.
The problem, of course, is that you don't know if other parts of the third party library are doing any reflection, and so removing an "unused" class might cause things to break in an obscure case that you haven't tested.
jar is just a zip file, so I guess you can. If you could get to the source, it's cleaner. Maybe try disassembling the class?
Adding to this question, can that improve performance? Since the classes not used would not be JIT compiled improving startup time or does the java automatically detect that while compiling to bytecode and do not even deal with the code that is not used?
This would be an interesting project (has anyone done it already?)
I presume you'd give the tool your jar(s) as a starting point, and the library jar to clean up. It could use reflection to determine which classes your jar(s) reference directly, and which are used indirectly down the call tree (this is not trivial at all, but doable). If it encounters any reflection code in any of the two places, it should give a very loud warning.