Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Which of multiple resources on classpath JVM takes?

People also ask

What is classpath resource in Java?

Classpath in Java is not only used to load . class files, but also can be used to load resources e.g. properties files, images, icons, thumbnails, or any binary content. Java provides API to read these resources as InputStream or URL.

Does JVM load all classes?

It doesn't load all the classes, but it knows where to look for them when you need them. They will be loaded when they are first needed.

What is classpath in JVM?

Classpath is a parameter in the Java Virtual Machine or the Java compiler that specifies the location of user-defined classes and packages. The parameter may be set either on the command-line, or through an environment variable.


It is specified by the order in which the resources (i.e. usually jar files) are specified using -classpath option. Resources 'earlier' on the classpath take precedence over resources that are specified after them. This can be also set in the manifest file of your application and then you don't need to provide -classpath option. You may want to check these articles on how to work with manifest files.

The exhaustive description of "how classes are found" can be found here, where the section on JAR-class-path Classes describes the logic of JAR-files searching.


The ClassLoader determines where a resource will be located (taken from ClassLoader JavaDoc):

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.

So wherever in your code Class#getResource or Class#getResourceAsStream is called, this happens (taken from Class.java)

public java.net.URL getResource(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        // A system class.
        return ClassLoader.getSystemResource(name);
    }
    return cl.getResource(name);
}

ClassLoader.java:

public URL getResource(String name) {
    URL url;
    if (parent != null) {
        url = parent.getResource(name);
    } else {
        url = getBootstrapResource(name);
    }
    if (url == null) {
        url = findResource(name);
    }
    return url;
}

where ClassLoader#findResource is actually to be overwritten by the ClassLoader implementation. This implies that the behavior is different on an application server, a TomCat or if you are running from a jar file, it depends on the ClassLoader implementations of the environment you are currently in.

Here is an example that you may use to trace what's going under the hood in your particular case.