How to automatically exclude not-used jar files from a maven project? - java

If I would like to write a program to automatically exclude not-used jar files from a maven project (regardless of what programming language I will use), how should I get start?
Currently, I have a stupid idea. Except the declared jar files, every time excluding a node of the dependency tree top down, then compile and run the project to see whether this jar file could be excluded.
I cannot find any other better ideas and I need help. Please share me with whatever come into your minds. If you know somebody else has done this before, please post the link to the source code or share with me its ideas. Thanks!!!!
By the way, what if I want to write a program automatically solving the dependency conflict problems? Is this possible? I know Such problems have bothered java developers a lot.

The idea of compiling for every removed dependency is good, but don't forget to launch the program also (some dependencies are required at runtime only).
I had to do that a few times, but I did manually (not automatically with a program), i removed all dependencies and added them one by one until code compiles, and until the program run OK.

The problem with approaches like this is the fact that even though everything might compile correctly, you are missing resources during runtime.
That might be the case, if you load classes and stuff with help of the Classloader or if you are using reflection to access classes and methods.
This gets even worse if you look at more dynamic languages aside of Java: the compiler won't help you that much anymore

Related

Android with AspectJ and building it with Ant on Eclipse

I'm new to Android and wanted to use AspectJ with it.
I had searched couple articles online and follow the instruction to have it working:
http://blog.punegtug.org/2010/11/adding-aspect-to-android.html
But I wanted to know whether if it's possible to separate the aspects away from the Android project. In the tutorial link above, it has both the Android App and the aspects inside the same project, but in many cases, we wanted to leave the Android Project untouched in its isolating spaces.
Let said I have AndroidProject in my Eclipse workspace, I would like to create a separate projects for my aspects called something like "AndroidAspectProject" which only contains the aspects for it.
I'm not sure whether this would work because it seems we need to let AspectJ compiler inject point cuts and advices to the .class files before creating the .dex files. In this sense, I may not able to do it in a separate project.
Does anyone try with this?
Another related question would be:
Is it possible to have Ant build the AndroidProject with AND without aspects on it? Can this be done outside of Eclipse?
I'm looking for a way to build different flavours as I'm only injecting pointcuts into the AndroidProject on dev/debug build, but will leave it untouched on release build.
Whether or not to do the compile-time aspects is a matter of whether or not you run the aspectj ant tasks. Have separate targets or properties for the AOP- and non-AOP-builds and either build one based on a target name or property, or build them both and change the artifact name.
IIRC Eclipse allows you to specify an Ant target to run on a build.
Inside of Eclipse, this is simple. Just add AndroidAspectProject to the aspect path of AndroidProject.
Inside of ant, there are several ways of doing this. But, the simplest is to define 2 targets. One that uses iajc and the other that uses javac to compile your sources. You then need to use a little ant magic switch between targets depending on whether you are compiling for dev or for production.

Experiences wanted: producing a jar artifact in IntelliJ

Developing with IntelliJ 9.0.2 Community Edition, on the Mac.
This is a follow-up to this post about including jar files in an artifact, which has not received any replies. I'm hoping that the reason is that somehow, in creating my artifact (or setting my project settings), I unwittingly did something which people don't tend to do, and which is causing my problem, and that by asking people here to share how they create jar artifacts and set up projects, I will discover what it is.
To recap: I have a Java project which depends on two library files. I need to package up the entire thing, with the jars inlined (such that on doing jar -tfv <filename> I see ALL the classes listed, including the ones in the two libraries), into a single jar file. I can make an artifact, I can add the library files to the Output Layout pane, but I CANNOT, no matter what I do, I cannot get the "Inline Artifact" item in the context menu to be selectable (i.e. non-grey) when I right-click on one or other library file.
The thing is, making a jar which contains library files as well as the project code is NOT an unusual situation in the Java world! So I figure there are lots of IntelliJ folks out there who have done what I need to do. And I would really like to hear from you folks.
What project settings do you use? (be specific, please :-)
And exactly how do you set up your jar artifacts? (again, as many specific details as possible, please :-)
Clearly, I'd be particularly interested to hear from folks with similar setups to mine (above) who are successfully doing what I need to do.
Grateful thanks in advance, folks.
I don't think there is much you can do from inside IntelliJ, but there are several ways to do it from outside by merging the JARs.
See here: Selective jar packaging

How do I find out what jar files are actually used when compiling a java project

I'm currently passing a very large classpath to javac to compile a java project.
I know that a number of those jar files aren't needed.
Is there a simple way of finding out which files aren't needed?
You need the Class Dependency Analyzer tool. To quote the introduction:
The purpose of this tool is to analyze Java™ class files in order to learn more about the dependencies between those classes.
True, it won't catch runtime dependencies - but short of running an exhaustive 100% coverage test suite you can never be sure you've caught all runtime dependencies.
If you expect runtime dependencies you should use the CDA as a first-pass, then do exhaustive testing of the resultant app to ensure that there are no jar files which were only referenced through runtime dependencies.
I guess that "remove them one by one and check if the application still compiles and works" is not the expected answer :)
(EDIT: While the approach suggested above can be a bit automated, it remains somehow painfull and there must be an alternative, at least for compile-time dependencies. After some googling, I found Jar Analyzer which seems to be a nice tool for this work as explained in this blog post:
Jar Analyzer scans for compile dependencies, meaning that it can create a tree of which JAR-files are needed to compile which JAR-files that are needed to compile these JAR-files, and so on. You get a very nice report/graph which shows you all the JAR-files and why they are in there.
You can also see the JAR-files that don't have any connection to your code, remove them and their children. What I found in our libs folder was that about 20% of the 150 JAR files in our libs folder were unused at compile time, and these were potential JARs to be removed.
The big aber is that you don't get any hint on which JAR-files are used only at runtime by means of discovery and reflection. And this is where the real work begins.
The only way to find out whether a JAR file is used at runtime is basically to take it out, start up your application and test every functionality. If you have an application of moderate size, performing a 100% regression test takes many hours. So in practice, I ended up doing alot of guessing, quick and dirty testing, and asking around to find out which of the runtime dependencies were actually in use.
It seems pretty easy to use: download, unzip and run the tool on a directory containing all jars. Or use the provided Ant task.)
You also have loosejar.jar which enables you to find the real jar dependencies of your project at runtime !
The compiler has a -verbose option, and it is quite verbose. It informs of each class that gets loaded and where it is loaded from!
While it's not quite user-friendly and it doesn't provide high-level analysis, I found it very useful for debugging classpath conflicts. This tells you the jars that get used (with help of grep), not the ones that don't get used.
The latest build of eclipse will warn you about unused imports in your source code
Check Classpath Helper

How to determine at runtime the path to a Mavenized Eclipse project directory

Total Maven newbie, trying (along with the rest of a sizeable team) to convert a monstrous pile of legacy code from ant over to Maven. It's working reasonably well, but I'm having the following problem.
I have a project, let's call it Core, that at runtime needs to load some files checked in under some different projects, let's call them Resources A and B. The Core code is started in a certain working directory, let's call it core/runtime, and there's a properties file it reads in order to determine what to load from Resources A and B, complete with the relative path to the resources in question, e.g.
resource.ham=../../resources-a/files/ham.rsrc
resource.eggs=../../resources-b/files/eggs.rsrc
(Yes, I'm aware this is sick and wrong and we should be loading resources as resources, from a JAR via a classloader and maybe some sort of container or dependency injector or whatever. Not my idea, not my current problem, not on the table to be fixed now.)
(Seriously, please don't bother suggesting we fix the underlying problem. We know we need to fix the underlying problem. We knew we needed to fix the underlying problem before we switched to Maven, and before we switched to Maven the stupid hack actually worked. I know it makes you feel good, but it's not helpful. This is a ten-year-old codebase with tens of thousands of classes and believe me, there are plenty of more important things wrong with it.)
This relative-path hack is only an issue in Eclipse, during development; in the actual deployed application the files live somewhere completely different and are loaded in a somewhat more sensible way.
Anyhow, this all worked fine when these were vanilla Eclipse projects, so the directories in question had paths like:
c:\workspace\core\runtime
c:\workspace\resources-a\files
c:\workspace\resources-b\files
However, now that these are checked out as Maven projects, the directories are now something like:
c:\workspace\core\runtime # Inexplicably unchanged
c:\workspace\maven.8675309\resources-a\files
c:\workspace\maven.6345789\resources-b\files
Questions:
Can I make these maven.7762323 directories go away?
If not, is there some way in Eclipse to get the path to a project directory, and then pass that as a system property in a launch configuration, or something like that?
Any solution has to be one I can check into SVN so the other developers on my team can use it out of the box.
Update
Okay, I figured out where the maven.[number] directories come from: When you select a parent directory in the SVN repository and say "Check out as Maven project", you get a maven.[number] directory corresponding to the parent, with all the actual projects as subdirectories. It would be very convenient, if only the code was actually all in the same parent directory, or even in the same SVN repository.
Can I make these maven.7762323 directories go away?
Where do they come from? What do you mean exactly by checked out as Maven projects?
(EDIT: As the OP wrote in a comment, these directories come from m2eclipse that allows to check out maven projects from SVN. I don't use this feature so I dont know much about it. However, after some googling, my understanding is that these names are kind of temporary and m2eclipse should rename them at the end of the checkout. Maybe something something went wrong with eclipse during the checkout. I'm not sure actually.)
If not, is there some way in Eclipse to get the path to a project directory, and then pass that as a system property in a launch configuration, or something like that?
Eclipse has a {build_project} variable that could be used in the arguments of a runtime configuration. Maybe {workpsace_loc} would be more appropriate in your case. The whole list is available with a description in the Arguments tab of a runtime configuration.
(EDIT: I'm still not sure I get the real goal but I have the feeling that using svn:externals could help.)
Okay, solution was to use {workspace_loc:project name} variables to set a handful of project directories as system properties, and use those to infer everything else. Now if I can just figure out how to get the ridiculous system for loading plugin JARs to work with Maven...

How can I identify unnecessary jars included in my project?

I'm working in a Java project where the axis 2 library from Apache is being used. The axis 2 library is composed of about 20 jar files and some of these are not used project. What I want to know if there is a method to identify which of those jar files are the unused ones.
I'm using the Eclipse IDE an I thought that one way to solve the problem is to add one jar at time until the I get no error messages about the missing classes. However, I'm not sure if this will work as some of the missing classes errors show up only at runtime.
Does anyone know a better way to solve this problem?
tattletale FTW
http://www.jboss.org/tattletale
JBoss Tattletale is a tool that can help you get an overview of the project you are working on or a product that you depend on.
The tool will provide you with reports that can help you
Identify dependencies between JAR files
Spot if a class is located in multiple JAR files
Spot if the same JAR file is located in multiple locations
With a list of what each JAR file requires and provides
I would follow your original idea of adding one jar at time until it compiles.
You're right that you can still find run-time errors, but unless the application is too big for a good coverage with manual tests, I would simply run and test it to add any missing jars.
I don't think you can reliably remove jars since classes may be resolved at runtime e.g. using
Class.forName(className);
You may be able to determine the class names used for the above, but it's unlikely.
Since classes will be requested/resolved at runtime, you could run your (comprehensive) test suite to determine whether stuff still works. But ultimately I would be very wary of removing jars from a package like Axis. I assume they're there for a purpose. Is the jar file size really a problem ?

Categories