1

I'm trying jdeprscan on my CentOS system. Here are the commands that I'm executing:

export classpath=<PATH/*>:<ANOTHER/PATH/*>:<SOME/OTHER/PATH/*>
jdeprscan --for-removal --verbose --class-path $classpath --release 9 <ANOTHER/PATH>/MyProject.jar

In spite of providing the classpath, I'm getting multiple errors of this sort

Processing class <some/class/in/MyProject.jar>...
error: cannot find class <some/class/in/a/different/jar>
error: cannot resolve Methodref <some/class/in/a/different/jar>.<method>:()Ljava/lang/String;

I've verified that the class mentioned in the error message are pretty much among one of the jars provided in the classpath. Strangely, it's not the case that I'm getting this error for every other classes referred in the jar that I'm scanning.

Few points for your consideration:

  • The are 50+ jars in the paths provided in the classpath
  • The jar that I'm trying to scan is residing in one of the paths mentioned in the classpath
  • I've tried jdeprscan available in JDK 9 & JDK 10 and getting the same errors
  • I've tried replacing the * in classpath with *.jar, doesn't help!

Is there anything wrong in the syntax that I'm following or is this a known bug in jdeprscan?

Curious Coder
  • 646
  • 8
  • 18
  • Please ensure that *To scan a JAR file or a set of class files, you must first ensure that all of the classes that the scanned classes depend upon are present in the classpath.* This can be confirmed as *Typically, you would use the same classpath as the one that you use when invoking your application.* – Naman Mar 28 '18 at 03:33
  • Agree, I've taken care of it. I even went ahead and extracted the jar to check whether the class file exists in it, and it does! – Curious Coder Mar 28 '18 at 04:04
  • Try listing the jars explicitly instead of using wildcards. – Stuart Marks Mar 28 '18 at 15:24

2 Answers2

3

Some preliminary notes on jdeprscsan from Oracle JDK 11 under Windows (I know the question related to JDK 9 on CentOS, but maybe the following applies as well...):

  • use wildcard "path/to/lib/*.jar" (it will not work without the ".jar" extension)
  • having a wildcard with more than one path is not supported (i.e. --class-path dir1/;dir2/*.jar throws a parse exception on the wildcard)
  • JARs in the directory specified by --class-path are added to the classpath and analyzed in alphabetical order, which may cause some error : cannot find class X messages because a JAR a.jar may depend on a JAR b.jar which is not yet loaded.

Based on the above, I found the 3 solutions below. Note that I did the same experiment with jdeprscan from the Oracle JDK 12.0.2 without any improvement.

Solution 1: all classes on the classpath

  1. unzip all JARs in a specific directory (ignore overwritted files such as META-INF/maven/pom.xml), e.g. mylib (note that at this stage, the mylibs directory contains only classes organized by directory packages, and no JARs).
  2. run the following command:

jdeprscan --for-removal --class-path /path/to/mylib /path/to/my-application.jar

Advantage: fast (very manual operations)

Drawback: only analyses the JAR file that has been specified on the command line (my-application.jar)

Solution 2: all JARs + a fat JAR on the classpath

  1. copy all JARs libs into a single mylib directory
  2. extract all files from JARs of mylib (ignore duplicate files) and repack them into a big JAR mylib/00lib.jar (a simple ZIP file renamed to .jar makes the trick)
  3. copy the mylib/00lib.jar to mylib/01lib.jar to ensure that it will be analysed
  4. run the following command:

    jdeprscan --for-removal --verbose --class-path path/to/mylib/*.jar path/to/my-application.jar

Advantage: fast (only a few manual operations) + analyses the JARs from mylib

Drawback: some of the jdeprscan messages will be related to the fat JAR 00lib.jar so you will not be able to determine immediately which library uses classes that are deprecated or removed from Java 9 or 11, but you can do it indirectly by looking at the class name, e.g. (a class from the com.atomikos library requires the missing class javax.jms.JMSException):

Processing class com/atomikos/datasource/xa/jms/JmsTransactionalResource...
error: cannot find class javax/jms/JMSException

Solution 3: reorder the JAR files on the classpath

  1. copy all JARs libs into a single mylib directory
  2. run the following command:

    jdeprscan --for-removal --class-path path/to/mylib/*.jar path/to/my-application.jar

  3. inspect the log to see error: cannot find class messages that are not supposed to be raised because the JAR exists in the lib directory. For each such library, copy the library with a name that is before the library name which reference it alphabetically speaking. For example, I have a JAR in the lib dir alpha.jar which depends on commons-lang-3.0.jar (which is not yet loaded in the classpath), so I copy commons-lang-3.0.jar to a0commons-lang-3.0.jar so that it will be loaded before alpha.jar. It is important to copy the JAR and not to rename it otherwise it may not be analyzed by jdeprscan (does not occur on every JAR). Once done, go back to step 2 until no error messages produced by library dependencies occurs.

Advantage: gives a clear view of which JAR uses deprecated/removed classes.

Drawback: takes a lot time (manual copy of each individual JARs which cause a classloading issue).

Conclusion

I use jdeprscan with Solution 2. This should be considered as a workaround (is it an incomplete tool documentation or a bug, I don't know...).

Julien Kronegg
  • 4,968
  • 1
  • 47
  • 60
0

If you happen to have a folder in PATH which has classes and JARs, it won't work. You'd have to specify the JARs individually (or get rid of the classes).

Alim Özdemir
  • 2,396
  • 1
  • 24
  • 35