问题
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/*.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 someerror : cannot find class X
messages because a JARa.jar
may depend on a JARb.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
- 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
mylib
directory - 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.jar
makes the trick) - copy the
mylib/00lib.jar
tomylib/01lib.jar
to 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
mylib
directory run the following command:
jdeprscan --for-removal --class-path path/to/mylib/*.jar path/to/my-application.jar
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 diralpha.jar
which depends oncommons-lang-3.0.jar
(which is not yet loaded in the classpath), so I copycommons-lang-3.0.jar
toa0commons-lang-3.0.jar
so 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