Finding unused jars used in an eclipse project - java

Are there any plugins/tools available to go through the classpath of an eclipse project (or workspace) and highlight any unused jars?

ClassPathHelper is a good start.
It automatically identifies orphan jars and much more.
The only limitation is with dependencies that are not defined in classes, e.g. in dependency injection framework configuration files.
You also have other options/complements, such as:
workingfrog "Relief", which relies on the ability to deal with real objects by examining their shape, size or relative place in space it gives a "physical" view on java packages, types and fields and their relationships, making them easier to handle.
Unnecessary Code Detector: a eclipse PlugIn tool to find unnecessary (dead) public java code.

UCDetector does not help for this : It does not work on JARs.
And for classpathHelper, I wan't able to find out an easy way just to list the orphan JARs (BTW, if someone has a tutorial for this, i am interested).
So, if you are also using Maven as I do, I find out this great Maven plugin, and I would like to share this solution with you.
Just type :
mvn dependency:analyze
And you will instantly get a list of unused JARs in your dependencies.
Very handy !

I found a very fast and interesting tool to archive this goal:
http://tattletale.jboss.org/
Just unzip the program and run:
java -Xmx512m -jar tattletale.jar ~/myjavaproject/mydistribution output
This will generate a very impressive report with different points (text from their site):
Identify dependencies between JAR files
Find missing classes from the classpath
Spot if a class/package 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
Verify the SerialVersionUID of a class
Find similar JAR files that have different version numbers
Find JAR files without a version number
Find unused JAR archives
Identify sealed / signed JAR archives
Locate a class in a JAR file
Get the OSGi status of your project
Remove black listed API usage
And generate the same reports for your .WAR and .EAR archives

You can use one of this plugins:
UCDetector or Classpath Helper

I know this is an old one, but if anyone else stumbles upon this, Eclipse does this by itself.
Navigate to Project properties->Java Code Style->Clean Up
Select the Eclipse [Built-in] and it does the following:
Change non static accesses to static members using declaring type
Change indirect accesses to static members to direct accesses
(accesses through subtypes)
Remove unused imports
Add missing '#Override' annotations
Add missing '#Override' annotations to implementations of interface
methods
Add missing '#Deprecated' annotations
Remove unnecessary casts
Remove unnecessary '$NON-NLS$' tags

In the Maven and Gradle projects you can use those plugins to identify unused dependencies.
For Maven : link
Use this in the pom.xml file plugin.
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
this will give as output. In this case we add commons-collections dependency to pom.xml, but do not use in the code.
For Gradle : link
Use this in the build.gradle file plugin.
plugins {
id "ca.cutterslade.analyze" version "1.7.1"
}
Using legacy plugin application:
this will give as output. In this case we add dependencies unusedDeclaredArtifacts to gradlefile, but do not use in the code.

Related

How to find java classes that needs a dependency in maven pom.xml file

I have a Maven based project, and I use IntelliJ. The pom.xml file probably contains dependencies that I don't need. How can I find which Java files (in particular the import statements) that need a specific dependency in the pom.xml file? Alternatively, how can I find which dependencies I don't need in the pom.xml?
I have tried to comment out a dependency from pom.xml, build the project and look what breaks. In at least one case, I saw no compile time problems, but there was a runtime problem. This method is also more effort than I want.
I have also tried to find information in the IntelliJ Project explorer, section "External Libraries". But the items listed there are not always present in the pom.xml file. Each versioned item there expands to a tree with a jar file on top, and I can ask IntelliJ about the usage of the contained items. I have found the usage of some packages contained in jar files, but the number of packages to investigate simply becomes too large.
Here is a dependency that I want to know if I need or not:
<!-- https://mvnrepository.com/artifact/com.googlecode.soundlibs/mp3spi -->
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>mp3spi</artifactId>
<version>1.9.5.4</version>
</dependency>
This particular dependency results in three items in the External Libraries list (there are two sub dependencies apparently). Asking IntelliJ for usage of these libraries, I can't find any usage in my own files. But if I remove the dependency from the pom.xml file, I get runtime problems.
Maven offers you the dependency:analyze goal which gives you the artifacts that are declared in your pom but not used by any part of your source code. Beware, though, that there may be dependencies that are only used at runtime.

Indirectly referenced from required .class files

I'm getting below error in STS:
The type org.springframework.core.env.EnvironmentCapable cannot be resolved. It is indirectly referenced from required .class files
This sounds like a transitive dependency issue. What this means is that your code relies on a jar or library to do something - evidently, you depend on Spring framework code. Well, all that Spring code also depends on libraries and jars.
Most likely, you need to add the corerctly versioned org.springframework.core jar to your classpath so that the EnvironmentCapable class can be found when your IDE attempts to build your project.
This might also be a jar collision issue as well, although that sounds less likely. When an application experiences jar collision (also known as "dll hell"), the compiler is finding multiple jars and classes with the same fully-qualified name. For example, let's say you added Spring to your classpath, along with the entire Tomcat server library. Well, those two jars may contain the same exact named classes, maybe the same version, maybe different versions. But either way, when the compiler looks for that EnvironmentCapable class, it finds two (in this contrived example) - one in the Spring jar and one in the Tomcat jar. Well, it doesn't know which one to choose, and so it throws a ClassDefNotFoundException, which would/could manifest itself as the error you experienced.
I faced same error while i work with spring security on spring-security-config.i jsut deleted that jar in maven repo and gave maven->update Project in eclipse.
it is resolved.Please try it once.
From command line, run "mvn clean install", you'll see project failed and you'll see artifacts in the logs that cause such a problem.
After that, remove artifacts from .m2/repository, then maven update from eclipse.
To avoid jar collision, make sure you declare your dependency versions under the properties tag in the aggregate pom.xml, and use the property name as a placeholder throughout the project. For example 4.2.5.RELEASE in the parent pom, and then in the child modules just use ${spring.version} instead of 4.2.5.RELEASE. This way you can avoid having two different versions of the same library on the classpath.
Also it is recommended to be consistent with the version of spring dependencies. Use the same version for spring-core, spring-web etc.
If you are using maven, then you can use the maven enforcer plugin to ensure dependency convergence, and avoid further issues with transitive dependencies.

Importing protocol buffer definitions between Maven projects

I currently manage a few separate Maven projects in which I use Protobufs as a serialization format and over the wire. I am using David Trott's maven-protoc plugin to generate the code at compile time.
All is good and well until I want those project to communicate between one another — or rather, use each other's protobufs. The protobuf language has an "import" directive which does what I want but I'm faced with the challenge of having project A exporting a ".proto" file (or possibly some intermediate format?) for project B to depend upon.
Maven provides a way for a project to bundle resources but AFAIK, these are meant to be used at runtime by the code and not by a goal during the compile / source generation phase — at least I haven't been able to find documentation that describes what I want to achieve.
I've found another way to achieve, and it doesn't involve any Maven magic. Diving into the code for the maven-protoc plugin, I found that this is a supported use case -- the plugin will look for and collect and .proto files in dependent jars and unpack them into a temporary directory. That directory is then set as an import path to the protoc invocation.
All that needs to happen is for the .proto file to be included in the dependency's package, which I did by making it a resource:
projects/a/src/main/resources/a.proto
Now in projects/b/pom.xml, add 'a' as a regular Maven dependency and just import a.proto from b.proto as if it existed locally:
b.proto:
import "a.proto";
This isn't ideal, since files names may clash between various projects, but this should occur rarely enough.
You can package your .proto files in a separate .jar/.zip in the project where they are generated, and publish them in your repository using a dedicated classifier. Using the assembly plugin might help here to publish something close to "source jars" that are built during releases.
Then, on projects using them, add previously created artifact as dependency.
Use the dependency plugin with the "unpack-dependencies" goal, and bind it to a phase before "compile".

How to examine required libraries?

I developing a web application with a lot of libraries like, Spring, Apache CXF, Hibernate, Apache Axis, Apache Common and so one. Each of these framework comes with a lot of *.jar libraries.
For development I simple take all of the delivered libraries and add them to my classpath.
For deployment not all of these libraries are required, so is there a quick way to examine all the required libraries (*.jar) which are used by my source code?
If you move your project to use Maven such things become easier:
mvn dependency:analyze
mvn dependency:tree
For your example, Maven + IDE + nice dependency diagrams could help allot.
See an example of this : it's much easier this way to figure out what happens in a project, and this way you don't need to add to your project "all delivered libraries" - just what it's required.
JDepend traverses Java class file
directories and generates design
quality metrics for each Java package.
JDepend allows you to automatically
measure the quality of a design in
terms of its extensibility,
reusability, and maintainability to
manage package dependencies
effectively.
So, as a quick, dirty, and potentially inefficient way, you can try this in Eclipse:
Create two copies of your project.
In project copy #2 remove all the jars from the classpath.
Pick a source file that now has errors because it can't resolve a class reference. Pick one of the unresolved classes and note its fully qualified class name.
Do Control-Shift-T and locate the unresolved class. You should be able to see which jar its contained in since all the jars are still in the classpath for project copy #1.
Add the jar that contains this unresolved class back into your classpath in project copy #2, then repeat steps 3 and 4 until all class references are resolved.
Unfortunately you're not done yet since the jar files themselves may also have dependencies. Two ways to deal with this:
Go read the documentation for all the third-party packages you're using. Each package should tell you what its dependencies are.
Run your application and see if you get any ClassNotFoundExceptions. If you do, then use Control-Shift-T to figure out what jar that class comes from and add it to your classpath. Repeat until your project runs without throwing any ClassNotFoundExceptions.
The problem with #2 is that you don't really know you've resolved all the dependencies since you can't simulate every possible execution path your project might take.

Get source JARs from Maven repository

Does anyone have any idea if you can find source JARs on Maven repositories?
Maven Micro-Tip: Get sources and Javadocs
When you're using Maven in an IDE you often find the need for your IDE to resolve source code and Javadocs for your library dependencies. There's an easy way to accomplish that goal.
mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc
The first command will attempt to download source code for each of the dependencies in your pom file.
The second command will attempt to download the Javadocs.
Maven is at the mercy of the library packagers here. So some of them won't have source code packaged and many of them won't have Javadocs.
In case you have a lot of dependencies it might also be a good idea to use
inclusions/exclusions to get specific artifacts, the following command
will for example only download the sources for the dependency with
a specific artifactId:
mvn dependency:sources -DincludeArtifactIds=guava
Source: http://tedwise.com/2010/01/27/maven-micro-tip-get-sources-and-javadocs/
Documentation: https://maven.apache.org/plugins/maven-dependency-plugin/sources-mojo.html
Configuring and running the maven-eclipse plugin, (for example from the command line mvn eclipse:eclipse )
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
If a project creates a jar of the project sources and deploys it to a maven repository, then you'll find it :)
Just FYI, sources artifacts are generally created by the maven-source-plugin. This plugin can bundle the main or test sources of a project into a jar archive and, as explained in Configuring Source Plugin:
(...) The generated jar file will be named by the value of the finalName plus "-sources" if it is the main sources. Otherwise, it would be finalName plus "-test-sources" if it is the test sources.
The additional text was given to describe an artifact ("-sources" or "-test-sources" here) is called a classifier.
To declare a dependency on an artifact that uses a classifier, simply add the <classifier> element. For example:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.7.ga</version>
<classifier>sources</classifier>
</dependency>
Note that you generally don't do this, most IDEs provide support to download sources (and/or JavaDoc) from the main artifact without declaring explicitly a dependency on them.
Finally, also note that some repository search engines allow searching for artifacts using the classifier (at least Nexus does with the advanced search). See this search for example.
The maven idea plugin for IntelliJ Idea allows you to specify whether or not sources and java doc should be resolved and downloaded
mvn idea:idea -DdownloadSources=true -DdownloadJavadocs=true
To download any artifact use
mvn dependency:get -Dartifact=groupId:artifactId:version:packaging:classifier
For Groovy sources this would be
mvn dependency:get -Dartifact=org.codehaus.groovy:groovy-all:2.4.6:jar:sources
For Groovy's javadoc you would use
mvn dependency:get -Dartifact=org.codehaus.groovy:groovy-all:2.4.6:jar:javadoc
This puts the given artifact into your local Maven repository, i.e. usually $HOME/.m2/repository.
dependency:sources just downloads the project dependencies' sources, not the plugins sources nor the sources of dependencies defined inside plugins.
To download some specific source or javadoc we need to include the GroupIds - Its a comma separated value as shown below
mvn dependency:sources -DincludeGroupIds=com.jcraft,org.testng -Dclassifier=sources
Note that the classifier are not comma separated, to download the javadoc we need to run the above command one more time with the classifier as javadoc
mvn dependency:sources -DincludeGroupIds=com.jcraft,org.testng -Dclassifier=javadoc
you can find info in this related question: Get source jar files attached to Eclipse for Maven-managed dependencies
if you use the eclipse maven plugin then use 'mvn eclipse:eclipse -DdownloadSources=true'
if you're using eclipse you could also open Preferences > Maven and select Download Artifact Sources, this would let the pom.xml intact and keep your sources or java docs (if selected) just for development right at your machine location ~/.m2
In Eclipse
Right click on the pom.xml
Select Run As -> Maven generate-sources
it will generate the source by default in .m2 folder
Pre-Requisite:
Maven should be configured with Eclipse.
In eclipse - click on the project then:
.
You can, if they are uploaded. Generally they are called "frameworkname-version-source(s)"
NetBeans, Context-Click
In NetBeans 8 with a Maven-driven project, merely context-click on the jar file list item of the dependency in which you are interested. Choose Download Sources. Wait a moment and NetBeans will automatically download and install the source code, if available.
Similarly you can choose Download Javadoc to get the doc locally installed. Then you can context-click some code in the editor and choose to see the JavaDoc.
Based on watching the Maven console in Eclipse (Kepler), sources will be automatically downloaded for a Maven dependency if you attempt to open a class from said Maven dependency in the editor for which you do not have the sources downloaded already. This is handy when you don't want to grab source for all of your dependencies, but you don't know which ones you want ahead of time (and you're using Eclipse).
I ended up using #GabrielRamierez's approach, but will employ #PascalThivent's approach going forward.
If you know the groupId and aritifactId,you can generate download url like this.
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
http://central.maven.org/maven2/ch/qos/logback/logback-classic/
and you will get a page like this, chose the version you need,just enjoy it!
I have also used the eclipse plugin to get the project into the eclipse workspace.
Since I've worked on a different project I saw that it is possible to work with eclipse but without the maven-eclipse-plugin. That makes it easier to use with different environments and enables the easy use of maven over eclipse. And that without changing the pom.xml-file.
So, I recommend the approach of Gabriel Ramirez.
Maven repositories do provide simple way to download sources jar.
I will explain it using a demonstration for "spring-boot-actuator-autoconfigure".
Go to maven repository -
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-actuator-autoconfigure
The page lists various versions. Click-on to desired one, let's say, 2.1.6.RELEASE - https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-actuator-autoconfigure/2.1.6.RELEASE
The page have link "View All" next to "Files". Click it -
https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-actuator-autoconfigure/2.1.6.RELEASE/
The page lists various files including the one for sources -
https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-actuator-autoconfigure/2.1.6.RELEASE/spring-boot-actuator-autoconfigure-2.1.6.RELEASE-sources.jar
Otherwise, you can always "git clone" the repo from github, if its there and get the specific code.
As explained by others, you can use "mvn dependency:sources" command the get and generate sources jar for the dependency you are using.
Note: Some dependencies will not have sources.jar, as those contains no source code but a pom file. e.g. spring-boot-starter-actuator.
As in this case:
Starter POMs are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors.
Reference: Intro to Spring Boot Starters
In IntelliJ IDEA you can download artifact sources automatically while importing by switching on Automatically download Sources option:
Settings → Build, Execution, Deployment → Build Tools → Maven → Importing
If you want find the source jar file for any of the artifact manually, go to maven repository location for the particular artifact and in Files click on 'view All'. You can find source jar file.
For debugging you can also use a "Java Decompiler" such as: JAD and decompile source on the fly (although the generated source is never the same as the original). Then install JAD as a plugin in Eclipse or your favorite IDE.
If you're using Eclipse, I would recommend downloading both the source and the Javadocs of third-party libraries.
Right click on project and download both as per the screenshot below.
Downloading Javadocs means that typically you can get contextual help for methods from third-party libraries, with useful description of parameters, etc. This is essential if you don't know the library well. In some cases I have found that Javadocs are available when the source isn't.

Categories

Resources