11

In my Java web app, I have these files:

/WEB-INF/classes/com/example/Foo.class
/WEB-INF/lib/example.jar <-- contains the class "com.example.Foo"

Will the class defined in the classes directory be used instead of the class defined in example.jar?

Thanks.

Michael
  • 34,873
  • 17
  • 75
  • 109

2 Answers2

14

The answer depends upon your container, it is container dependent. In general, /WEB-INF/classes is preferred to classes in a jar file in WEB-INF/lib.

For Tomcat, the order is the following:

Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:

  1. Bootstrap classes of your JVM
  2. System class loader classes
  3. /WEB-INF/classes of your web application
  4. /WEB-INF/lib/*.jar of your web application
  5. Common class loader classes

But if you're using a different container, you need to consult the documentation for that server.

Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
  • And I think any classes in example.jar still get Foo.class from the jar file. – Amir Raminfar Dec 02 '11 at 20:39
  • 1
    @AmirRaminfar No, it should always use the same version of the class, otherwise madness ensues. – Matthew Farwell Dec 02 '11 at 20:42
  • So you are saying Bar.class in `example.jar` that imports Foo.class will load Foo.class in `web-inf/classes` ? Because that doesn't sound right and it would be a security restriction I am sure. – Amir Raminfar Dec 02 '11 at 20:45
  • 1
    @AmirRaminfar Are you saying that Baz.class (in classes) which needs Foo.class (in classes) which calls Bar.class (in example.jar, and depends upon Foo.class) will use the Foo.class from example.jar instead of the one that is already loaded? I think not. – Matthew Farwell Dec 02 '11 at 20:49
  • No I am talking about Bar.class in the jar file! `example.jar!/com/example/Bar.class` will load Foo.class in `example.jar/com/example/Foo.class` – Amir Raminfar Dec 02 '11 at 20:50
  • Only one way to test this. But I doubt if what you say is true because then I can load SecureClass.class in my webapp and basically overtake everything. – Amir Raminfar Dec 02 '11 at 20:51
  • @AmirRaminfar Well, it's your webapp...if you want to compromise your own web app that's OK with me... – Michael Dec 02 '11 at 20:56
7

So there is only one way to find out. I wrote a test :)

├── example
│   ├── example.iml
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── test
│       │           ├── Bar.java
│       │           └── Foo.java
│       └── test
│           └── java
│               └── testexample
│                   └── TestFoo.java
├── pom.xml
├── test.iml
└── web
    ├── pom.xml
    ├── src
    │   ├── main
    │   │   └── java
    │   │       └── test
    │   │           └── Foo.java
    │   └── test
    │       └── java
    │           └── junittest
    │               └── TestFooInWeb.java
    └── web.iml

16 directories, 11 files

My finding was that in TestFoo.java prints

Hello from example.jar
Hello from example.jar

And for TestFooInWeb.java prints

Hello from web app
Hello from web app

Both tests have this in the test class:

public class TestFooInWeb/TestFoo {
    @Test
    public void testHello() {
        System.out.println(new Foo().sayHello());
    }

    @Test
    public void testHelloFromBar() {
        new Bar().sayHelloForFoo();
    }
}

So all at the end, I stand corrected. You apprantly can load a completely different class and all Jar files will use that new class. This makes sense because the ClassLoader will first look at the classes directory. I am not sure if I agree with it because it sounds suspicious and I can overwrite security classes.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • Very detailed experiment, thank you! I'm pretty sure you can't override the core Java classes, though. So, for example, you couldn't create a `java.lang.String` class and have it do something nasty. Btw, what are those ".iml" files?? – Michael Dec 03 '11 at 01:55
  • Those .iml files are intellij ide. And you are right you cannot over write system classes. If you look at what Mathew wrote, the order is system classpath then web classpath. – Amir Raminfar Dec 03 '11 at 04:30
  • confused. what is SayHelloForFoo()? Where's your example.jar? Where's this 'classes' directory? – john k Mar 10 '23 at 18:29