The Fragile Base Class Problem
Resolution is the process of replacing names by relative addresses and offsets. Normally resolution occurs during compilation and linking, which occurs before loading and execution. This creates a special problem in C++ called the Fragile Base Class Problem (also known as the Fragile Super Class Problem and the Constant Recompilation Problem). For example, assume the following class is declared and compiled: class Employee { private: char *name; int ssn; double salary; public: // etc. } Later a derived class is declared and compiled: class Secretary: public Employee { private: int wpm; // typing speed in words/minute public: void display() { cout << wpm; } // etc. } According to the rules of object layout dictated by the C++ compiler, a Secretary object is an Employee object extended by an integer variable (i.e. wpm). Hence the occurence of wpm inside display() will be bound to the relative address: this + offset(wpm) where offset(wpm) = sizeof(Employee) + a little bit This binding will occur at link time if Employee and Secretary are contained in seperate files. Now assume the Employee class is modified to contain an extra field: class Employee { private: char *name; int ssn; double salary; int tenure; // = # years on the job public: // etc. } Since sizeof(Employee) has changed, the Secretary::display() method contains the wrong offset for wpm, hence must be recompiled. Java avoids this problem by reversing the usual "link then load" order. This is possible because the byte code produced by a Java compiler may contain unresolved names (i.e. symbolic references). The corresponding Java declarations are: class Employee { private String name; private int ssn; private double salary; // etc. } and class Secretary extends Employee { private int wpm; public void display(System.out.println(wpm); } // etc. } First the class Secretary is loaded into memory by a class loader object. This causes the Employee class to be loaded. Next the Secretary class is linked. This is a four step process: 1. verify opcodes, jump targets, type consistencies, etc. 2. allocate memory for static variables 3. resolve symbolic references (or put it off until later!) 4. initialize static variables Finally, main() is called. Now suppose the Employee class is redefined: class Employee { private String name; private int ssn; private double salary; private int tenure; // new field // etc. } Again the old Secretary class is loaded along with the new Employee class. Following the load phase, the link phase resolves all symbolic references. This includes replacing the occrence of the name wpm inside display() with an offset which (may) depend on sizeof(Employee), but since this occurs AFTER the new Employee class has been loaded, the correct offset is computed, hence there is no need to recompile the Secretary class! Two final observations: 1. Resolution may be postponed until instance creation time, or even until execution time. 2. Unlike the C++ compiler, the Java compiler doesn't determine object layout. (This is determined by the loader.) Hence the offset of wpm does not necessarily depend on sizeof(Employee) in Java. See http://java.sun.com/doc/language_environment for more info.