Search code examples
javawarjavap

How to check imports of a *.war file?


I have an old war-file where the source code was lost as my old machine passed away.

It did run there with tomcat 8 with no problems.

On my new machine, when tomcat (8 as well as 9) tries to deploy the war file, it gives me

... 10 more Caused by: java.lang.ClassNotFoundException: javafx.scene.image.Image at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1358) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1180) ... 23 more

I don't remember having used javafx in my code directly.

So, how to check imports of a *.war file to see which class or library causes the trouble?

I have tried javap on sample classes but never see any imports.

I am aware that javafx is no longer part of the runtime environment, which obviously is the immediate cause of the problem, but, for this application, javafx should not be needed at all.


Solution

  • Run javap -v -constants on your .class files to see class references.

    You might want to pipe the output through grep "= Class" (Linux) or findstr "=\ Class" (Windows), or maybe just grep javafx / findstr javafx.

    E.g. even a super simple "Hello World" program uses multiple classes.

    public class Test {
        public static void main(String[] args) {
            System.out.println("Hello World");
        }
    }
    

    Output

    C:\path\to\classes\classes>javap -v -constants Test.class | grep "= Class"
       #1 = Class              #2             // Test
       #3 = Class              #4             // java/lang/Object
      #17 = Class              #18            // java/lang/System
      #25 = Class              #26            // java/io/PrintStream
    

    It doesn't show the use of String. To see why, look at the full constant pool, which for that small program is:

    Constant pool:
       #1 = Class              #2             // Test
       #2 = Utf8               Test
       #3 = Class              #4             // java/lang/Object
       #4 = Utf8               java/lang/Object
       #5 = Utf8               <init>
       #6 = Utf8               ()V
       #7 = Utf8               Code
       #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
       #9 = NameAndType        #5:#6          // "<init>":()V
      #10 = Utf8               LineNumberTable
      #11 = Utf8               LocalVariableTable
      #12 = Utf8               this
      #13 = Utf8               LTest;
      #14 = Utf8               main
      #15 = Utf8               ([Ljava/lang/String;)V
      #16 = Fieldref           #17.#19        // java/lang/System.out:Ljava/io/PrintStream;
      #17 = Class              #18            // java/lang/System
      #18 = Utf8               java/lang/System
      #19 = NameAndType        #20:#21        // out:Ljava/io/PrintStream;
      #20 = Utf8               out
      #21 = Utf8               Ljava/io/PrintStream;
      #22 = String             #23            // Hello World
      #23 = Utf8               Hello World
      #24 = Methodref          #25.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
      #25 = Class              #26            // java/io/PrintStream
      #26 = Utf8               java/io/PrintStream
      #27 = NameAndType        #28:#29        // println:(Ljava/lang/String;)V
      #28 = Utf8               println
      #29 = Utf8               (Ljava/lang/String;)V
      #30 = Utf8               args
      #31 = Utf8               [Ljava/lang/String;
      #32 = Utf8               SourceFile
      #33 = Utf8               Test.java
    

    Since you don't need all the string constants, you could use grep -v Utf8:

       #1 = Class              #2             // Test
       #3 = Class              #4             // java/lang/Object
       #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
       #9 = NameAndType        #5:#6          // "<init>":()V
      #16 = Fieldref           #17.#19        // java/lang/System.out:Ljava/io/PrintStream;
      #17 = Class              #18            // java/lang/System
      #19 = NameAndType        #20:#21        // out:Ljava/io/PrintStream;
      #22 = String             #23            // Hello World
      #24 = Methodref          #25.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
      #25 = Class              #26            // java/io/PrintStream
      #27 = NameAndType        #28:#29        // println:(Ljava/lang/String;)V