Find unused classes in a Java Eclipse project - java

I have a large Eclipse project in which there exist several classes which, although they ceased to be used anywhere, were never marked #Deprecated.
How can I easily find all of these?

I also like to use UCDetector:
UCDetector (Unecessary Code Detector) is a Open Source eclipse PlugIn Tool to find unecessary (dead) public java code. It also tries to make code final, protected or private.
Bonus: it can also find cyclic dependencies between classes
(also a number of other tools -- including Findbugs -- knows how do do that too)
Caveat: Cid mentions in the comments:
UCDetector shall not work if there are interface implementations which will be known only at runtime.
It incorrectly marks the implementation classes as unused.
Update 2017: static code analysis has evolved quite a bit in 8 years.
Using SonarLint for Eclipse, you can use the the latest SonarJava 4.6 plugin to analyze your code.
It will find dead code.

ProGuard can be used to print a report of unused classes/methods. It's a pain to supply all the dependent jars to it, though.
These options list unused classes, fields, and methods in the application mypackage.MyApplication:
-injars in.jar
-libraryjars <java.home>/lib/rt.jar
-dontoptimize
-dontobfuscate
-dontpreverify
-printusage
-keep public class mypackage.MyApplication {
public static void main(java.lang.String[]);
}

Just use Analyze | Inspect Code with appropriate inspection enabled (Unused declaration under Declaration redundancy group).
Using IntelliJ 11 CE you can now "Analyze | Run Inspection by Name ... | Unused declaration"

Related

Failing to obfuscate Java code with ProGuard

I'm trying to optimize / obfuscate a java project with ProGuard.
I extract the project as a runnable jar from eclipse, and it runs just fine.
When I try to compress it with ProGuard, I get thousands of warning and errors, in particular at the end:
Note: there were 1 classes trying to access generic signatures using reflection.
You should consider keeping the signature attributes
(using '-keepattributes Signature').
Note: there were 14 unresolved dynamic references to classes or interfaces.
You should check if you need to specify additional program jars.
Note: there were 2 class casts of dynamically created class instances.
You might consider explicitly keeping the mentioned classes and/or
their implementations (using '-keep').
Note: there were 15 accesses to class members by means of introspection.
You should consider explicitly keeping the mentioned class members
(using '-keep' or '-keepclassmembers').
Warning: there were 13229 unresolved references to classes or interfaces.
You may need to add missing library jars or update their versions.
If your code works fine without the missing classes, you can suppress
the warnings with '-dontwarn' options.
Warning: there were 61 instances of library classes depending on program classes.
You must avoid such dependencies, since the program classes will
be processed, while the library classes will remain unchanged.
Warning: there were 18 unresolved references to program class members.
Your input classes appear to be inconsistent.
You may need to recompile the code.
The external libs I used in the project are added to the jar upon exporting it from eclipse. ("Extract required libraries into jar"). I did not use the "repack into jar" option because it really slows jars down.
The libs in particular are:
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
Am I doing something fondamentally wrong here?
I have tried without success the suggestions of proguard, and my code compiles in eclipse with no warnings.
It's a very big project so I can't really provide an MCVE, but if someone could point me in the right direction here as to what I'm missing, I'd really appreciate it.
Example of the warning: (It goes on for every single method)
http://pastebin.com/m9hX9LJA
Obviously this might be too general of a problem for you guys to fix, however I might be doing some major obvious mistake that I'm not realizing, that's what I'm going for with this.
Notes are just suggestions, but warnings point out inconsistencies in the input. Notably, the 13229 unresolved references suggest that you are providing the main code of your application (with -injars), but not its libraries (with -injars or -libraryjars). I don't know of Eclipse's Extract or Repack options, but you should check the contents of your input jar(s).
See the ProGuard manual > Troubleshooting > Warning: can't find referenced class.

Program to obfuscate files before compilation?

I am working with ForgeGradle (Minecraft Forge modding platform).
I'd like to obfuscate my mod before publishing but the nature of Forge platform won't allow me to do it by simply running program like ProGuard after compilation (with defined libraries).
Why?
The structure goes like this:
Mod -> Forge -> Minecraft
Since Minecraft uses its own obfuscated classes and ForgeGradle compilator is not DIRECTLY obfuscating Mod's code to fit with Minecraft's one, it is not possible to use MC.jar as library while using ProGuard. Compiled Forge Mod is actually decoded by Forge in runtime using SRG names. The logic behind this is not easily explainable so I'll just note: I cannot obfuscate .jar in a way to fit with libraries.
So I though - I could just take my mod's code (.java files) and rename all fields/methods/classes that are MINE before Forge compilation.
Is there a software that would allow me to pick number of .java files and "obfuscate" them in a way to not reaname references that don't belong to them?
EDIT (more explanation):
Mod's code has 3 states: Development, Compiled, Running.
I will try to give an example:
Let's say there is a decompiled method ItemSword.onHit() inside Minecraft.jar
And its compiled (obfuscated) version look like this: bca.aa(), also all packages are lost (flattened).
In mod's development state of code (.java) to make reference to it we simply make: ItemSword.onHit()
When we compile mod the call will look like this (.class): ItemSword.func_ab4234() - this is the SRG I was talking about.
Now when the mod will be loaded to game, forge will translate "ItemSword" to "bca" and "func_ab4234()" to "aa()"
Because of this I can't even add proper library - there IS NONE. I will always get (in ProGuard) NoClassDefFound Warning and I can't ignore it (it will crash compilation).
So after this edit - Is it still possible to make obfuscation with ProGuard (considering I cannot have "good" library assigned)?
Did you try the proguard options?
http://proguard.sourceforge.net/manual/usage.html
e.g. for Serializable classes and other stuff put this to your proguard configuration (you also can preserve complete classes if you like):
<!-- With this code serializable classes will be backward compatible -->
<keepnames implements="java.io.Serializable"/>
<!-- or for native access:-->
<keepclasseswithmembernames>
<method access="native"/>
</keepclasseswithmembernames>
<!--Preserve all public classes, and their public and protected fields and methods.-->
<keep access="public">
<field access="public protected"/>
<method access="public protected"/>
</keep>
If I got your question, you want to obfuscate your own code, not anything beyond that. That's what ProGuard is actually quite good at. Let's assume you created your classes in the packages com.foo and com.bar. You can use this simple ProGuard command to only obfuscate your own classes:
-keep class !com.foo.**,!com.bar.** { *; }
It tells ProGuard to not obfuscate any members of classes which do not belong to either com.foo or com.bar.
If you are getting NoClassDef errors, you added the wrong library. I guess you are using some kind of IDE (perhaps eclipse). Have a look at the libraries your project references to find the correct library classpath (e.g. a jar file). You basically need to find the classpath used for compiling your code, ProGuard will take that as well and everything should work.

Find unused public members in Eclipse

I have a class which has 1600 public static members. I must found and delete the unused ones. Is there a way to do it in Eclipse.
There exists a Eclipse plugin Unused Code Detector (http://www.ucdetector.org/).
It can process a specific file or the entire project, searching for unused members/methods.
Ucdetector: You can install a plugin from this link. It works pretty well we have been using it in all our projects. It generates a html report as well it can mark warnings in eclipse. It helps you find unused classes, methods and variables. Only thing it dosen't do well is finding if a class is used via reflection only or where instance is created via spring. In these cases it still shows that class is unused.
http://ucdetector.sourceforge.net/update
Another thing you can do to clean up other types of unsed code is
GoTo Window>Preferences>Java>Compiler>Error/Warnings
Now look for uncessary code section and tweak the settings as you desire to cleanup further.
I hope it helps :)

Android Dx Error1, Failed to convert to Dalvik format

I'm getting desperate with this Problem: I want to export/run my Android Application with one additional .jar I added to the buildpath. I'm sure I added it correctly, there are 5 other .jars included and they all work fine.
with this special one I get the mentioned error.
I've already tried everything that can be found in this question:
"Conversion to Dalvik format failed with error 1" on external JAR
and several other links google spat out. The main Problem is, I actually do not understand what the message I appended want's to tell me because if I add all the jars to a "normal" javaproject, it runs perfectly fine...
Developing on Android 4.0.3,
proguard 4.8,
adt 16.0.1.v201112150204-238534,
eclipse 3.7.1.r37
please help me
[2012-07-18 10:45:48 - myapp] Dx warning: Ignoring InnerClasses attribute for an anonymous inner
class (iaik.xml.crypto.XSecProvider$1) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced
by a compiler that did not target the modern .class file format. The
recommended solution is to recompile the class from source, using an
up-to-date compiler and without specifying any "-target" type options.
The consequence of ignoring this warning is that reflective operations
on this class will incorrectly indicate that it is not an inner
class.
...
...
[2012-07-18 10:45:48 - myapp] Dx warning: Ignoring InnerClasses attribute for an anonymous inner
class (iaik.xml.crypto.XSecProvider$2) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced
by a compiler that did not target the modern .class file format. The
recommended solution is to recompile the class from source, using an
up-to-date compiler and without specifying any "-target" type options.
The consequence of ignoring this warning is that reflective operations
on this class will incorrectly indicate that it is not an inner
class.
Ill-advised or mistaken usage of a core class (java.* or javax.*) when
not building a core library.
This is often due to inadvertently including a core library file in
your application's project, when using an IDE (such as Eclipse). If
you are sure you're not intentionally defining a core class, then this
is the most likely explanation of what's going on.
However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example, from a
non-Android virtual machine project. This will most assuredly not
work. At a minimum, it jeopardizes the compatibility of your app with
future versions of the platform. It is also often of questionable
legality.
If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine distribution,
as opposed to compiling an application -- then use the
"--core-library" option to suppress this error message.
If you go ahead and use "--core-library" but are in fact building an
application, then be forewarned that your application will still fail
to build or run, at some point. Please be prepared for angry customers
who find, for example, that your application ceases to function once
they upgrade their operating system. You will be to blame for this
problem.
If you are legitimately using some code that happens to be in a core
package, then the easiest safe alternative you have is to repackage
that code. That is, move the classes in question into your own package
namespace. This means that they will never be in conflict with core
system classes. JarJar is a tool that may help you in this endeavor.
If you find that you cannot do this, then that is an indication that
the path you are on will ultimately lead to pain, suffering, grief,
and lamentation.
[2012-07-18 10:45:48 - myapp] Dx 1 error; aborting
[2012-07-18 10:45:48 - myapp] Conversion to Dalvik format
failed with error 1
This is how my project looks int he explorer:
The problem is that the jar you are including has a class in the java.* or javax.* namespace. dx does not allow this, as mentioned in the last big error message.
If you actually need these classes, you'll need to move them to a different package, using something like the jarjar tool. Otherwise, you'll need to remove them from the jar -- it may be possible to have proguard to remove them before everything gets dx'd, I'm not sure.
I faced the same problem, I finally resolved it by exporting my private library explicitly.
Like:
Project >> properties >> Java Build Path >> Libraries >> Add External Jars.
Note: Removed my all private libraries from libs folder. I know it is not correct but it worked for me.
Thanks,
Anil
Do as follows :
project
> properties
> java build path
> libraries
> remove all including android jars
Now, go the project browser, right click on the project you are working on, then
android tools
> fix project properties.
Do a clean and then build.
Just restart eclipse, and the error won't occur anymore
If you work on Win7 change this line:
call %java_exe% -jar "%PROGUARD_HOME%"\lib\proguard.jar %*
in proguard.bat file to this:
call %java_exe% -jar "%PROGUARD_HOME%"\lib\proguard.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
proguard.bat is in:
[Android SDK Installation Directory]\tools\proguard\bin\proguard.bat
Edit:
I hope a combine of these help you:
1-Try to delete libraries projects from your project.
2-Try to export your project(as archive file),delete project and it's source from workspace and then import it again.
3-Try to remove your jars from path,do clean-build and then add them again to your project.
I had the same error when using my own obfuscated lib jar.
my log:
warning:Ignoring InnerClasses attribute for an anonymous inner class that doesn't come with an associated EnclosingMethod attribte.This class was probably prouduced by a compiler that did not target the morden .class file format...
And I solved it like this:before I obfuscate my jar,I added "-keepattributes EnclosingMethod" to the proguard.cfg(or proguard-project.txt in latest android adt version).
Agree with hasanghaforian. The easiest solution is to remove libraries project.
Right click your project->Properties->Java Build Path then remove Library Projects

Obfuscating jar file using proguard

I used proguard to obfuscate my jar file.
During processing I got the following errors:
Initializing...
Warning: tdvep.jmNb: can't find referenced class QSYGWO
Warning: tdvep.qmfsfjttKdvEpNz: can't find referenced class FVTYBN
Warning: tdvep.qsfboBcSw$qsffmtssf: can't find referenced class UGKTLU
Warning: tdvep.qsffmtssf: can't find referenced class DREQUQ
Warning: there were 4 unresolved references to classes or interfaces.
You may need to specify additional library jars (using '-libraryjars').
Please correct the above warnings first.
So guide me to resolve this warnings.
Have you checked the ProGuard troubleshooting section - Problems while processing.
If there are unresolved references to classes or interfaces, you most likely forgot to specify an essential library. For proper processing, all libraries that are referenced by your code must be specified, including the Java run-time library. For specifying libraries, use the -libraryjars option.
For example, if ProGuard complains that it can't find a javax.crypto class, you probably still have to specify jce.jar, next to the more common rt.jar.
If you're missing a library and you're absolutely sure it isn't used anyway, you can try your luck with the -ignorewarnings option, or even the -dontwarn option. Only use these options if you really know what you're doing though.
For example, if you're developing for Android, and ProGuard complains that it can't find a java.awt class, then some library that you are using is referring to java.awt. This is a bit shady, since Android doesn't have this package at all, but if your application works anyway, you can let ProGuard accept it with "-dontwarn java.awt.**".

Categories

Resources