Joonas Pulakka
Joonas Pulakka

Reputation: 36577

Is Java class loader guaranteed to not load classes that aren't used?

Is there a guarantee that (the default, system) Java class loader doesn't attempt to load classes that aren't referred to in the code being run? A couple of examples of what I mean:

Quickly testing it seems to work as assumed above, and it wouldn't make much sense to load unused classes anyway, but is there any guarantee on this?

Addition: It seems that my "static blocks are run when a class is first loaded" statement above is somewhat incorrect. It's definitely possible to load classes (one thing) without running them (another thing). So I'm interested in both cases; guarantees about classes not getting loaded, and not getting run.

Upvotes: 15

Views: 3837

Answers (7)

Stephen C
Stephen C

Reputation: 718796

There is no such guarantee1 wrt the loading of the classes.

However, you are guaranteed that static blocks won't be run prematurely. The events that trigger class initialization are specified in JLS 12.4.1.

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.

1 - It is observed that current generation Java implementations do not load classes unnecessarily, but that is not a guarantee. The only guarantees are what it written in the official specifications.

Upvotes: 9

OscarRyz
OscarRyz

Reputation: 199225

Yes.

Think about the following. If you add the following code to that library.jar class:

 public ShutDown {static { System.exit(-1); }}

That code won't be loaded automatically by the default system, because none of the existing code has a reference or knows about the ShutDown class, nor had a way to load it, and the Java class loader don't just go around trying to load random classes from the jar.

The way classes are loaded are described in the previous answers, if you review them carefully none of them include a "If there is a class in the jar it would be loaded" of some sort.

Upvotes: 0

Raja Shankar Kolluru
Raja Shankar Kolluru

Reputation: 602

There are no such guarantees as other posters have mentioned. But your question and your concern don't follow from each other. For you to leave library.jar out, you don't need such guarantees.

There are a number of frameworks that discover the presence or absence of other frameworks during runtime. Ex: Commons-logging discovers a bunch of other frameworks. Spring web flow discovers what the scripting framework is (is it OGNL for instance) during runtime. These frameworks are obviously compiled using all dependent frameworks but they dont have to exist during runtime.

Hence it is perfectly acceptable to leave library.jar out during runtime.

Upvotes: 0

mdma
mdma

Reputation: 57707

If you are not using reflection, then you can statically check which classes are used using a dead-code removal tool, such as ProGuard. It will analyse your code and determine all the classes used. On the basis of that, it removes unused code, including unused code in libraries.

If your code or libraries use reflection to load classes, then you will need to run a full coverage test of your application and log all the classes loaded, which you instruct ProGuard to keep.

Upvotes: 1

josefx
josefx

Reputation: 15656

The java specification states

The loading process is implemented by the class ClassLoader and its subclasses. Different subclasses of ClassLoader may implement different loading policies. In particular, a class loader may cache binary representations of classes and interfaces, prefetch them based on expected usage, or load a group of related classes together.

So the classloader is free to prefetch classfiles.

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the reference to the field is not a compile-time constant (§15.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.

The static blocks will be executed only when the class is first used.

Upvotes: 4

The thing that pulls in classes is the references to them from Java byte code (which again may pull in other classes). If the classes you run, do not have any reference to class X, it will not be loaded.

Note however that there is newer ways to register e.g. services through META-INF. Those classes need to be loaded too.

You can always run with "-verbose" to see the classes as they load - the order clearly shows that they are loaded when needed.

Upvotes: 2

Donal Fellows
Donal Fellows

Reputation: 137567

I don't think there's any such guarantee. For one thing, I've seen code scanners which do things like processing annotations from whole package hierarchies/JARs during application startup; they'd violate that assumption right away.

Why does this matter? You're usually after highly controllable system loading so anything where would matter would be somewhere where you'd want to force it anyway…

Upvotes: 1

Related Questions