750 likes | 760 Views
Explore the techniques of dynamic loading, reflection, and reconfiguration to support runtime software evolution and avoid the cost of whole-system restart. Learn how shared libraries and linker-assisted dynamic loading can enhance memory-space utilization and enable the sharing of common libraries.
E N D
Lecture XII: Runtime Software Evolution CS 4593Cloud-Oriented Big Data and Software Engineering
Agenda • Why runtime software evolution? • Techniques • Dynamic Loading • Reflection • Reconfiguration
Why runtime software evolution? • Web services are supposed to be running all the time • Users expectation • Requirements of downstream services • Changes are always required • Patches of bugs • Adding features • Cost of whole-system restart
Whole-system restart may cost a lot • Turning off • Data backup • Record and stop ongoing sessions • Turning on • Initialize all platform services, e.g., database server, logging server, … • Recover sessions
Techniques to Support • Dynamic Loading • Reflection • Just-in-time Compilation • Reconfiguration
Dynamic Loading • What happens to your program? • After it is compiled, but before it can be run?
Executable files • The OS expects executable files to have a specific format • Header info • Code locations • Data locations • Code & data
Executable files • The OS expects executable files to have a specific format • Symbol Table • List of names of things defined in your program and where they are defined • List of names of things defined elsewhere that are used by your program, and where they are used.
#include <stdio.h> int main () { printf (“hello, world\n”) } Symbol defined in your program and used elsewhere main Symbol defined elsewhere and used by your program printf Example
#include <stdio.h> extern int errno; int main () { printf (“hello, world\n”) <check errno for errors> } Symbol defined in your program and used elsewhere main Symbol defined elsewhere and used by your program printf errno Example
Two-step operation (in most systems) • Linking: Combining a set of programs, including library routines, to create a loadable image • Resolving symbols defined within the set • Listing symbols needing to be resolved by loader
Two-step operation (in most systems) • Loading: Copying the loadable image into memory, connecting it with any other programs already loaded, and updating addresses as needed • (In Unix) interpreting file to initialize the process address space • (in all systems) kernel image is special (own format)
From source code to a process Source(.c, .cc) • Binding is the process of mapping names to addresses • Most compilers produce relocatable object code • Addresses relative to zero • The linker combines multiple object files and library modules into a single executable file • Addresses also relative to zero Compiler Object(.o) Other Objects(.o) Static libraries(.a) Linker Executable Dynamic libraries (.dll) Loader In-memory Image
From source code to a process Source(.c, .cc) • The Loader reads the executable file • Allocates memory • Maps addresses within file to physical memory addresses • Resolves names of dynamic library items Compiler Object(.o) Other Objects(.o) Static libraries(.a) Linker Executable Dynamic libraries (.dll) Loader In-memory Image
Printf.c HelloWorld.c gcc Static Library gcc Printf.o ar HelloWorld.o Linker a.Out(or name ofyour command) Loader Memory Static Linking and Loading
Classic Unix • Linker is inside of gcc command • Loader is part of exec system call • Executable image contains all object and library modules needed by program • Entire image is loaded at once • Every image contains copy of common library routines • Every loaded program contain duplicate copy of library routines
Dynamic Loading • Routine is not loaded until it is called • Better memory-space utilization; unused routine is never loaded. • Useful when large amounts of code are needed to handle infrequently occurring cases.
Program-controlled Dynamic Loading • Requires: • A load system call to invoke loader (not in Unix/Linux) • ability to leave symbols unresolved and resolve at run time (not in Unix/Linux) • E.g., void myPrintf (**arg) { static int loaded = 0; if (!loaded ) { load (“printf”); loaded = 1; printf(arg); } }
Linker-assisted Dynamic Loading • Programmer marks modules as “dynamic” to linker • For function call to a dynamic function • Call is indirect through a link table • Each link table initialized with address small stub of code to locate and load module.
Linker-assisted Dynamic Loading • For function call to a dynamic function • When loaded, loader replaces link table entry with address of loaded function • When unloaded, loader replaces table entry with stub address • Static data cannot be made dynamic
Shared Libraries • Observation – “everyone” links to standard libraries (libc.a, etc.) • Consume space in • every executable image • every process memory at runtime • Would it be possible to share the common libraries? • Automatically load at runtime?
Shared libraries (continued) • Libraries designated as “shared” • .so, .dll, etc. • Supported by corresponding “.a” libraries containing symbol information • Linker sets up symbols to be resolved at runtime • Loader: Is library already in memory? • If so, map into new process space • “map,” an operation to be defined • If not, load and then map
Run-time Linking/Loading Printf.c HelloWorld.c gcc gcc Printf.o HelloWorld.o Linker Save disk space. Startup faster. Might not need all. a.Out(or name ofyour command) Shared Library Run-time Loader Loader Memory
Dynamic Linking • Complete linking postponed until execution time. • Stub used to locate the appropriate memory-resident library routine..
Dynamic Linking • Stub replaces itself with the address of the routine, and executes the routine. • Operating system needs to check if routine is in processes’ memory address space. • Dynamic linking is particularly useful for libraries.
Dynamic Shared Libraries • Static shared libraries requires address space pre-allocation • Dynamic shared libraries – address binding at runtime • Code must be position independent • At runtime, references are resolved as • Library_relative_address + library_base_address
Linking and Loading - Summary • Linker – key part of OS – not in kernel • Combines object files and libraries into a “standard” format that the OS loader can interpret • Resolves references and does static relocation of addresses • Creates information for loader to complete binding process • Supports dynamic shared libraries
Techniques to Support • Dynamic Loading • Reflection • Reconfiguration
What Is Reflection • Java™ Technology provides two ways to discover information about an objectat runtime • Traditional runtime class identification • The object’s class is available at compile and runtime • Most commonly used • Reflection • The object’s class may not be availableat compile or runtime
What Is Reflection • “Reflection in a programming language context refers to the ability to observe and/or manipulate the inner workings of the environment programmatically.”1 • “The reflection API represents, or reflects, the classes, interfaces, and objects in the current Java™ virtual machine.”2
The History of Reflection • Introduced in JDK™ 1.1 release to support the JavaBeans™ specification • Used throughout the JDK™ software and Java runtime environment (JRE) • Java™ Foundation Classes API (JFC) • Jini™ connection technology • JavaMail™ API • JDBC™ API • Improved in Java 1.2 SDK • Further refined in Java 1.3 SDK
Why Runtime Class Identification • Java™ technology takes advantageof polymorphism • New subclasses easily added • Bulk of behaviors inherited from its superclass • No impact on other subclasses of the superclass
Why Runtime Class Identification • Java™ technology takes advantageof polymorphism • At runtime, the JVM™ takes advantage of late dynamic binding • Messages are directed to the correct method
Runtime Class Identification Example Code • Class loading occurs at first instantiation
How the Class Object Works • Every class loaded into the JVM™ has a Class object • Corresponds to a .class file • The ClassLoader is responsible for finding and loading the class into the JVM™ • At object instantiation… • The JVM™ checks to see if the class is already loaded into the virtual machine • Locates and loads the class if necessary • Once loaded, the JVM™ uses the loadedclass to instantiate an instance
Late Dynamic Binding • The JRE does not require that all classes are loaded prior to execution • Different from most other environments • Class loading occurs when the class is first referenced • Late Dynamic Binding is… • Important for polymorphism • Message propagation is dictated at runtime • Messages are directed to the correct method • Essential for reflection to be possible
Class Literals • Using Class Literals is the second way to reference an object’s class • Added in the JDK™ 1.1 release • All classes, interfaces, arrays, and primitive types have class literals • Primitive types have corresponding wrapper classes • Examples: Triangle.CLASS int.TYPE
The instanceof Keyword • The instanceof keyword is the third way to reference an object’s class • Used with both classes and interfaces • Returns true if the object is a species of aspecified class • Subclasses will also answer true • Code becomes structurally bound to the class hierarchy • Several limitations on the referenced class • Must be a named class or interface • The class constant cannot be the Class class • Example: if (x instanceof Circle) ((Circle) x).setRadius (10);
The Reflection API • The reflection API is the fourth way to reference an object’s class • Reflection allows programs to interrogate and manipulate objects at runtime • The reflected class may be… • Unknown at compile time • Dynamically loaded at runtime
Core Reflection Classes • java.lang.reflect • The reflection package • Introduced in JDK 1.1 release • java.lang.reflect.AccessibleObject • The superclass for Field, Method, and Constructor classes • Suppresses the default Java language access control checks • Introduced in JDK 1.2 release
Core Reflection Classes (Cont.) • java.lang.reflect.Array • Provides static methods to dynamically create and access Java arrays • java.lang.reflect.Constructor • Provides information about, and access to, a single constructor for a class
Core Reflection Classes (Cont.) • java.lang.reflect.Field • Provides information about, and dynamic access to, a single field of a class or an interface • The reflected field may be a class (static) field or an instance field
Core Reflection Classes (Cont.) • java.lang.reflect.Member • Interface that reflects identifying information about a single member (a field or a method) or a constructor • java.lang.reflect.Method • Provides information about, and access to, a single method on a class or interface • java.lang.reflect.Modifier • Provides static methods and constantsto decode class and memberaccess modifiers
Core Reflection Classes (Cont.) • JDK 1.3 release additions • java.lang.reflect.Proxy • Provides static methods for creating dynamic proxy classes and instances • The superclass of all dynamic proxy classes created by those methods • java.lang.reflect.InvocationHandler • Interface • Interface implemented by the invocation handler of a proxy instance
Commonly Used Classes • java.lang.Class • Represents classes and interfaces within a running Java™ technology-based program • java.lang.Package • Provides information about a package that can be used to reflect upon a class or interface • java.lang.ClassLoader • An abstract class • Provides class loader services
Using Reflection • Reflection allows programs to interrogate an object at runtime without knowing the object’s class • How can this be… • Connecting to a JavaBean™ technology- based component • Object is not local • RMI or serialized object • Object dynamically injected
What Can I Do With Reflection • Literally everything that you can do if you know the object’s class • Load a class • Determine if it is a class or interface • Determine its superclass and implemented interfaces • Instantiate a new instance of a class • Determine class and instance methods • Invoke class and instance methods • Determine and possibly manipulate fields • Determine the modifiers for fields, methods, classes, and interfaces • Etc.
Here Is How To… • Load a class Class c = Class.forName (“Classname”) • Determine if a class or interface c.isInterface () • Determine lineage • Superclass Class c1 = c.getSuperclass () • Superinterface Class[] c2 = c.getInterfaces ()
Here Is How To… • Determine implemented interfaces Class[] c2 = c.getInterfaces () • Determine constructors Constructor[] c0 = c.getDeclaredConstructors () • Instantiate an instance • Default constructor Object o1 = c.newInstance () • Non-default constructor Constructor c1 = c.getConstructor (class[]{…}) Object i = c1.newInstance (Object[] {…})