Is there a way to automatically find out which Java classes are actually loaded (either during compile time, as far as that's possible, or during the runtime of an application), and to throw out all other classes from a JAR to create a smaller JAR? Does that actually make sense in practice?
I am talking about the application classes for an application JAR. Usually there are lots of libraries in an application, and an application rarely needs all features of those libraries. So I suspect that would make a considerably smaller application. In theory that might be done for example via an Java agent that logs which classes and resources are read by one or several runs of an application (or even just by java -verbose:class), and a maven plugin that throws out all other classes from a jar-with-dependencies. Is there already something like that?
Clarification: I am not talking about unused dependencies (JARs that are not used at all), but about removing unused parts of each included JAR.
Well, the Maven Shade Plugin has an option minimizeJar when creating an Uber-JAR for your application:
https://maven.apache.org/plugins/maven-shade-plugin/
But, as others already pointed out, this is quite dangerous, as it regularly fails to detect class accesses which are done via Reflection or other dynamic references.
It may not be a good approach automate, as application can use reflection to initialise objects or one JAR is dependent on another JAR.
Only way that I can think of is to remove each JARs one by one and check if application runs as expected. Then again in this approach all modules of the application has to be tested, since one module can work without particular dependency and other may not.
Better solution is to take care while developing. The application developer must be careful in adding a dependency and removing unwanted dependency after his/her piece of code is done.
Global strategy.
1) Find all the classes that are loaded during runtime.
2) List of all the classes available in the classpath.
3) Reduce your class path by creating copies of jars containing only classes you need.
I have done 1 and 2 part so I can help you.
1) Find out all the classes that are loaded. You need 100 % code coverage (I am not talking about tests, but production). So run all possible scenarios, so all the classes your app needs will be loaded and logged.
To log loaded classes try several approaches. Reflection, –verbose:class flag, also you can learn about java agent. It allows to modify methods during runtime. This is an example of some java agent code or another java agent example
2) To find all the classes available in jar, you can write a program. You need to know all places where application jars are placed. Loop throw these jars (You can use ZipFile), loop through ZipFileEntry entries, and collect all classes.
3) After that write a script or program that reassembles your application. For example, now you can create a new jar file for each library and put there only needed classes.
Also you may use a tool (again, you are a programmer, so write a program), which checks code for classes dependence. You do not want to remove classes if they are used for compilation. When I was a student, I wrote code alanyzer, which builds an oriented graph for classes dependencies.
As #Gokul Nath KP notes, I did this before. I manually change gradle and maven dependencies, removing one by one, and then full regression test. It took me a week (our application was small comparing to modern world enterprise systems created by hundreds of developers).
So, be creative, and in case of success, your project will be used by millions!
In one of the projects I'm building for they're using my domain objects jar but only importing one package through OSGi.
Is there a way I can tell maven to check and make sure that none of the classes in this package refer to any other packages and fail the build if so?
You'd be probably looking either for:
a unit-testing solution like JUnit4OSGI
or even one for integration testing, like Pax-Exam
I've made good experiences with the latter one.
I have a java maven project in a jar file (bigfat jar, the whole project in one file). I want to do an integration test on it (first option is blackbox testing, but I will settle for whitebox if it is an easier path).
What I am really interested about is the end-to-end result, however some of the interfaces in the middle are APIs and sockets which are hardcoded inside the jar to communicate with a specific port or with a specific website.
What I want to do is to override the classes inside the jar file that are related to these interfaces, and code them with my model interfaces.
The whole new testing project will not go into production, this is purely for testing purposes.
I am using maven.
Any ideas are more than welcome
I have a java package foo.bar. It contains few classes, that are frequently modified, improved etc in this time of project.
I don't want any developer to use classes from the other packages in this one. I want this package to be separated in its usage. So this package must be isolated.
I could make an external jar, but that would introduce much more handling for little number of classes, that it does not make sense.
I want this inspection to be run from my build process.
I tried several code-inspection tools (pmd...) but I was not able to configure this. How to do this?
This is for a desktop GUI application. I need to store my Java classes and JUnit test classes in two separate folders.
How do I go about doing this in Eclipse, rather what is the best approach to do this?
Create two different projects for swings and test cases. Because I feel that it separates the functionality. Don't write anything under default package, as it is said that its not a good practice.
I like mavens folder structure. src/main/java and src/test/java
Then use the same package names in each folder so the unit test class has access to the variables in your class.
in eclipse it can generate a unit test class for you. definitely use different folders though so when you package your code you can easily leave the tests out.