问题
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?
回答1:
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/*.jarthrows a parse exception on the wildcard) - JARs in the directory specified by
--class-pathare added to the classpath and analyzed in alphabetical order, which may cause someerror : cannot find class Xmessages because a JARa.jarmay depend on a JARb.jarwhich 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
- 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). - 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
- copy all JARs libs into a single
mylibdirectory - extract all files from JARs of
mylib(ignore duplicate files) and repack them into a big JARmylib/00lib.jar(a simple ZIP file renamed to.jarmakes the trick) - copy the
mylib/00lib.jartomylib/01lib.jarto ensure that it will be analysed 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
- copy all JARs libs into a single
mylibdirectory run the following command:
jdeprscan --for-removal --class-path path/to/mylib/*.jar path/to/my-application.jarinspect the log to see
error: cannot find classmessages 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 diralpha.jarwhich depends oncommons-lang-3.0.jar(which is not yet loaded in the classpath), so I copycommons-lang-3.0.jartoa0commons-lang-3.0.jarso that it will be loaded beforealpha.jar. It is important to copy the JAR and not to rename it otherwise it may not be analyzed byjdeprscan(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...).
回答2:
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).
来源:https://stackoverflow.com/questions/49525496/jdeprscan-throws-cannot-find-class-error