Reputation: 36577
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:
framework.jar
which I know to contain references to another library.jar
's classes in it, but I'm using only such part of the framework that doesn't contain those references. Is it safe to leave library.jar
out?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
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
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
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
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
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:
The static blocks will be executed only when the class is first used.
Upvotes: 4
Reputation: 75376
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
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