Вы находитесь на странице: 1из 37

Java and the JVM

This include our work-in-progress on the working and architecture of Java Virtual Machine (JVM) infrastructure. Our research on JVM architectures that deliver scalable high performance for scientific applications on large numbers of processors. This structure allows rapid prototyping of our research ideas by confining changes in JVM design to a small number of modules. We describe the basic architecture of JVM and give an example of how its components may be used to compose object creation subsystems with different locality policies.JVM provides compile once and execute anywhere technique.
A Java Virtual Machine is a piece of software that is implemented on non-virtual hardware and on standard operating systems. A JVM provides an environment in which Java bytecode can be executed, enabling such features as automated exception handling, which provides "root-cause" debugging information for every software error (exception), independent of the source code. A JVM is distributed along with a set of

standard class libraries that implement the Java application programming interface (API). Appropriate APIs bundled together form the Java Runtime Environment (JRE). JVMs are available for many hardware and software platforms. The use of the same bytecode for all JVMs on all platforms allows Java to be described as a "compile once, run anywhere" programming language, as opposed to "write once, compile anywhere", which describes cross-platform compiled languages. Thus, the JVM is a crucial component of the Java platform. Java bytecode is an intermediate language which is typically compiled from Java, but it can also be compiled from other programming languages. For example, Ada source code can be compiled to Java bytecode and executed on a JVM.

Bytecode verifier A basic philosophy of Java is that it is inherently "safe" from the standpoint that no user program can "crash" the host machine or otherwise interfere inappropriately with other operations on the host machine, and that it is possible to protect certain methods and data structures belonging to "trusted" code from access or corruption by "untrusted" code executing within the same JVM. Furthermore, common programmer errors that often lead to data corruption or unpredictable behavior such as accessing off the end of an array or using an uninitialized pointer are not allowed

to occur. Several features of Java combine to provide this safety, including the class model, the garbage-collected heap, and the verifier. The JVM verifies all bytecode before it is executed. This verification consists primarily of three types of checks:

Branches are always to valid locations Data is always initialized and references are always typesafe Access to "private" or "package private" data and methods is rigidly controlled.

The first two of these checks take place primarily during the "verification" step that occurs when a class is loaded and made eligible for use. The third is primarily performed dynamically, when data items or methods of a class are first accessed by another class. The verifier permits only some bytecode sequences in valid programs, e.g. a jump (branch) instruction can only target an instruction within the same method. Furthermore, the verifier ensures that any given instruction operates on a fixed stack location, allowing the JIT compiler to transform stack accesses into fixed register accesses. Because of this, that the JVM is a stack architecture does not imply a speed penalty for emulation on register-based architectures when using a JIT compiler. In the face of the code-verified JVM architecture, it makes no difference to a JIT compiler whether it gets named imaginary registers or imaginary stack positions that must be allocated to the target architecture's registers. In fact, code verification makes the JVM different from a classic stack architecture whose efficient emulation with a JIT compiler is more complicated and typically carried out by a slower interpreter.

Code verification also ensures that arbitrary bit patterns cannot get used as an address. Memory protection is achieved without the need for a memory management unit (MMU). Thus, JVM is an efficient way of getting memory protection on simple architectures that lack an MMU. This is analogous to managed code in Microsoft's .NET Common Language Runtime, and conceptually similar to capability architectures such as the Plessey 250, and IBM System/38. The original specification for the bytecode verifier used natural language that was "incomplete or incorrect in some respects." A number of attempts have been made to specify the JVM as a formal system. By doing this, the security of current JVM implementations can more thoroughly be analyzed, and potential security exploits prevented. It will also be possible to optimize the JVM by skipping unnecessary safety checks, if the application being run is proved to be safe. Bytecode instructions The JVM has instructions for the following groups of tasks:

Load and store Arithmetic Type conversion Object creation and manipulation Operand stack management (push / pop) Control transfer (branching) Method invocation and return Throwing exceptions Monitor-based concurrency

The aim is binary compatibility. Each particular host operating system needs its own implementation of the JVM and runtime. These JVMs interpret the bytecode semantically the same way,

but the actual implementation may be different. More complex than just emulating bytecode is compatibly and efficiently implementing the Java core API that must be mapped to each host operating system. Secure execution of remote code A virtual machine architecture allows very fine-grained control over the actions that code within the machine is permitted to take. This is designed to allow safe execution of untrusted code from remote sources, a model used by Java applets. Applets run within a VM incorporated into a user's browser, executing code downloaded from a remote HTTP server. The remote code runs in a restricted "sandbox", which is designed to protect the user from misbehaving or malicious code. Publishers can purchase a certificate with which to digitally sign applets as "safe", giving them permission to ask the user to break out of the sandbox and access the local file system, clipboard or network. C to bytecode compilers From the point of view of a compiler, the Java Virtual Machine is just another processor with an instruction set, Java bytecode, for which code can be generated. The JVM was originally designed to execute programs written in the Java language. However, the JVM provides an execution environment in the form of a bytecode instruction set and a runtime system that is general enough that it can be used as the target for compilers of other languages. Because of its close association with the Java language, the JVM performs the strict runtime checks mandated by the Java specification. That requires C to bytecode compilers to provide their own "lax machine abstraction", for instance producing compiled code that uses a Java array to represent main memory

(so pointers can be compiled to integers), and linking the C library to a centralized Java class that emulates system calls. Most or all of the compilers listed below use a similar approach. Several C to bytecode compilers exist

NestedVM translates C to MIPS machine language first before converting to Java bytecode. Cibyl works similarly to NestedVM but targets J2ME devices. LLJVM compiles C to LLVM IR, which is then translated to JVM bytecode. C2J is also GCC-based, but it produces intermediary Java source code before generating bytecode. Supports the full ANSI C runtime. Axiomatic Multi-Platform C supports full ANSI C 1989, SWT, and J2ME CDC 1.1 for mobile devices. Java Backend for GCC, possibly the oldest project of its kind, was developed at The University of Queensland in 1999. Javum is an attempt to port the full GNU environment to the JVM, and includes one of the above compilers packaged with additional utilities.

Compilers targeting Java bytecode have been written for other programming languages, including Ada and COBOL.

History of a Java

1992 Oak for a PDA on a SPARC (*7) 1995 Official release as Java Internet 1997 picoJava Suns Java processor 1998 RTSJ specification start as JSR-01 1999 split into J2SE and J2EE 2000 J2ME 2002 RTSJ final release 2002 first version of JOP

Java features Simple and object oriented Look and feel of C Simplified object model with single inheritance Portability Java compiler generates bytecodes Runtime systems for various platforms Size and behavior of basic data types defined Write once, run/debug anywhere Java features Availability Windows, Linux, Solaris, Embedded systems Compiler and runtime are free Free IDEs: Eclipse, Netbeans Library

Rich class library Part of the definition Standard GUI toolkit Built-in model for concurrency Threads at the language level Synchronization Libraries are thread-safe Safety No Pointer! Extensive compile-time checking Runtime checking Automatic memory management GC

What is a Virtual Machine? A virtual machine (VM) is an abstract computer architecture Software on top of a real hardware Can run the same application on different machines where the VM is available.

Java Technology The Java programming language

The library (JDK) The Java virtual machine (JVM) Instruction set Binary format Verification

Java Primitive Data Types byte 8-bit integer (signed) short 16-bit integer (signed) int 32-bit integer (signed) long 64-bit integer (signed) float 32-bit floating-point(IEEE 754-1985) double 64-bit floating-point(IEEE 754-1985.

Objects Everything belongs to an object (or a class) No global variables Namespace for objects Single inheritance Interfaces Allocated on the heap Shared among threads No free()garbage collector

The Java Virtual Machine An abstract computing machine that executes bytecode programs An instruction set and the meaning of those instructions the bytecodes A binary format the class file format An algorithm to verify the class file Runtime environment for Java Implementation NOT defined Runs Java .class files Has to conform to Suns specification

Implementations of the JVM Interpreter Simple, compact Slow Just-in-time compilation State-of-the-art for desktop/server Too resource consuming in embedded systems Batch compilation Hardware implementation JVM Data Types reference Pointer to an object or array int 32-bit integer (signed) long 64-bit integer (signed) float 32-bit floating-point(IEEE 754-1985) double 64-bit floating-point(IEEE 754-1985) No boolean, char, byte, and shorttypes Stack contains only 32-bit and 64-bit data Memory Areas for the JVM Method area Class description

Code Constant pool Heap Objects and Arrays Shared by all threads Garbage collected Stack Thread private Logical stack that contains: Invocation frame Local variable area Operand stack Not necessary a singlestack Local variables and operand stack are accessed frequently JVM Instruction Set 32 (64) bit stack machine Variable length instruction set Simple to very complex instructions Symbolic references Only relative branches Java for Embedded Systems? + Simpler than C/C++ + Safer than C/C++ + Threads are part of the language -Interpreting JVM is slow -JIT needs a lot of memory -GC and real-time?

Java/JVM Java language definition Class library The Java virtual machine (JVM) An instruction set the bytecodes A binary format the class file An algorithm to verify the class file Safe OO Language No pointers Type-safety Garbage Collection Built in model for concurrency Platform independent Very rich standard library

Java James Gosling, Bill Joy, Guy Steele, and GiladBracha. The Java Language Specification, Addison-Wesley, 2000, JavaSpec. JVM Tim Lindholmand Frank Yellin. The Java Virtual Machine Specification. Addison-Wesley, 1999

The JVM Architecture The JVM is basically a stack-based machine, with a 32-bit word size, using 2s complement arithmetic.

1would be an Intel machine-language program too. Information Representation/Storage. THE JVM ARCHITECTURE :Registers Registers The JVM register set2 is fairly small: _ pc: program counter _ optop: pointer to the top of the operand stack (a kind of work space; see below) for the currentlyactive method _ frame: pointer to the stack frame of the currently-active method _ vars: pointer to the beginning of the local variables of the currently-active method Memory Areas _ the Stack: The JVM architecture is very much stack-oriented. Most instructions access the stack in some way. The stack is also used for method calls, as with many classical machine architectures. A method call produces a new stack frame, which is pushed onto the Stack for that program.3 and a return pops the frame from the programs Stack. A stack frame is subdivided into the following. a Local Variables section: All the local variables and arguments for the method are stored here, one per slot (i.e. one variable per word), with the arguments stored first and then the locals. The arguments and locals are stored in order of their declaration. In the case in which the method is an instance method, i.e. is not declared static, slot 0 will contain a pointer to the object on which this method is

operating, i.e. the object addressed as this in the programs source code. an Operand Stack section: This is the area on which the methods instructions operate. Almost all JVM instructions are stack-based; e.g. an add instruction pops the top two elements of the stack, adds them, and pushes the sum back onto the stack. So the Operand Stack portion of a methods stack frame is what we are referring to when we refer to an instruction as operating on the stack. a Frame Data section: We will not go into the details of this. _ the Method Area: The classes used by the executing program are stored here. This includes: the bytecode and access types of the methods of the class (similar to the .text section of a UNIX program, except for the access types) Remember, in the case of a real Java chip, these would be real registers, but in the JVM setting, these registers, as well as the instruction set, are simulated by the java program. More precisely, for that thread, since many Java programs are threaded. Information Representation/Storage: THE JVM ARCHITECTURE The Instruction Set the static variables of the class (their values and access types, i.e public, private etc.) The pc register points to the location within the Method Area of the JVM instruction to be executed next.

The Method Area also includes the Constant Pool. It contains the string and numeric literals used by the program, e.g. float W = 1.2; and also contains information on where each method is stored in the Method Area. _ the Heap: This is where Java objects exist. Whenever the Java new operation is invoked to create an object, the necessary memory is allocated within the heap. This space will hold the instance variables for the object, and a pointer to the location of the objects class in the Method Area. The Instruction Set Structure Most instructions are a single byte in length, consisting only of an op code, but there are a few multi-byte instructions as well. As mentioned earlier, almost all JVM instructions involve operand stack operations. Example Consider the following source code, Minimum.java: public class Minimum { public static void main(String[] Args) { int X,Y,Z; X = Integer.parseInt(Args[0]); Y = Integer.parseInt(Args[1]); Z = Min(X,Y); System.out.println(Z); } Just as in C, where a call to malloc() results in memory space being allocated from the heap, and just as in C++, where a call

to new results in space being taken from the heap. Information Representation/Storage: THE JVM ARCHITECTURE , The Instruction Set public static int Min(int U, int V) { int T; if (U < V) T = U; else T = V; return T; } } References _ Bill Venners book, Inside the Java Virtual Machine. Available on the Web (with many helpful URL links) at www.artima.com.

The Architecture of the Java Virtual Machine In the Java virtual machine specification, the behavior of a virtual machine instance is described in terms of subsystems, memory areas, data types, and instructions. These components describe an abstract inner architecture for the abstract Java virtual machine. The purpose of these components is not so much to dictate an inner architecture for implementations. It is more to provide a way to strictly define the external behavior of implementations. The specification defines the required behavior of any Java virtual machine implementation in terms of these abstract components and their interactions. Figure 1.1 shows a block diagram of the Java virtual machine that includes the major subsystems and memory areas described in the specification. As mentioned in previous chapters, each

Java virtual machine has a class loader subsystem: a mechanism for loading types (classes and interfaces) given fully qualified names. Each Java virtual machine also has an execution engine: a mechanism responsible for executing the instructions contained in the methods of loaded classes.

Figure 1.1. The internal architecture of the Java virtual machine. When a Java virtual machine runs a program, it needs memory to store many things, including bytecodes and other information

it extracts from loaded class files, objects the program instantiates, parameters to methods, return values, local variables, and intermediate results of computations. The Java virtual machine organizes the memory it needs to execute a program into several runtime data areas. Although the same runtime data areas exist in some form in every Java virtual machine implementation, their specification is quite abstract. Many decisions about the structural details of the runtime data areas are left to the designers of individual implementations. Different implementations of the virtual machine can have very different memory constraints. Some implementations may have a lot of memory in which to work, others may have very little. Some implementations may be able to take advantage of virtual memory, others may not. The abstract nature of the specification of the runtime data areas helps make it easier to implement the Java virtual machine on a wide variety of computers and devices. Some runtime data areas are shared among all of an application's threads and others are unique to individual threads. Each instance of the Java virtual machine has one method area and one heap. These areas are shared by all threads running inside the virtual machine. When the virtual machine loads a class file, it parses information about a type from the binary data contained in the class file. It places this type information into the method area. As the program runs, the virtual machine places all objects the program instantiates onto the heap. See Figure 1-2 for a graphical depiction of these memory areas.

Figure 1.2. Runtime data areas shared among all threads. As each new thread comes into existence, it gets its own pc register (program counter) and Java stack. If the thread is executing a Java method (not a native method), the value of the pc register indicates the next instruction to execute. A thread's Java stack stores the state of Java (not native) method invocations for the thread. The state of a Java method invocation includes its local variables, the parameters with which it was invoked, its return value (if any), and intermediate calculations. The state of native method invocations is stored in an

implementation-dependent way in native method stacks, as well as possibly in registers or other implementation-dependent memory areas. The Java stack is composed of stack frames (or frames). A stack frame contains the state of one Java method invocation. When a thread invokes a method, the Java virtual machine pushes a new frame onto that thread's Java stack. When the method completes, the virtual machine pops and discards the frame for that method. The Java virtual machine has no registers to hold intermediate data values. The instruction set uses the Java stack for storage of intermediate data values. This approach was taken by Java's designers to keep the Java virtual machine's instruction set compact and to facilitate implementation on architectures with few or irregular general purpose registers. In addition, the stackbased architecture of the Java virtual machine's instruction set facilitates the code optimization work done by just-in-time and dynamic compilers that operate at run-time in some virtual machine implementations. See Figure 1-3 for a graphical depiction of the memory areas the Java virtual machine creates for each thread. These areas are private to the owning thread. No thread can access the pc register or Java stack of another thread.

Figure 1-3. Runtime data areas exclusive to each thread. Figure 1-3 shows a snapshot of a virtual machine instance in which three threads are executing. At the instant of the snapshot, threads one and two are executing Java methods. Thread three is executing a native method. In Figure 1-3, as in all graphical depictions of the Java stack in this book, the stacks are shown growing downwards. The "top" of each stack is shown at the bottom of the figure. Stack frames for currently executing methods are shown in a lighter shade.

For threads that are currently executing a Java method, the pc register indicates the next instruction to execute. In Figure 1-3, such pc registers (the ones for threads one and two) are shown in a lighter shade. Because thread three is currently executing a native method, the contents of its pc register--the one shown in dark gray--is undefined. The Java by Bill Venners The Class Loader Subsystem The part of a Java virtual machine implementation that takes care of finding and loading types is the class loader subsystem. "Introduction to Java's Architecture," gives an overview of this subsystem. , "Security," shows how the subsystem fits into Java's security model. This chapter describes the class loader subsystem in more detail and show how it relates to the other components of the virtual machine's internal architecture. The Java virtual machine contains two kinds of class loaders: a bootstrap class loader and user-defined class loaders. The bootstrap class loader is a part of the virtual machine implementation, and user-defined class loaders are part of the running Java application. Classes loaded by different class loaders are placed into separate name spaces inside the Java virtual machine. The class loader subsystem involves many other parts of the Java virtual machine and several classes from the java.lang library. For example, user-defined class loaders are regular Java objects whose class descends from java.lang.ClassLoader. The methods of class ClassLoader allow Java applications to access Virtual Machine

the virtual machine's class loading machinery. Also, for every type a Java virtual machine loads, it creates an instance of class java.lang.Class to represent that type. Like all objects, userdefined class loaders and instances of class Class reside on the heap. Data for loaded types resides in the method area. Loading, Linking and Initialization The class loader subsystem is responsible for more than just locating and importing the binary data for classes. It must also verify the correctness of imported classes, allocate and initialize memory for class variables, and assist in the resolution of symbolic references. These activities are performed in a strict order: 1. Loading: finding and importing the binary data for a type 2. Linking: performing verification, preparation, and (optionally) resolution a. Verification: ensuring the correctness of the imported type b. Preparation: allocating memory for class variables and initializing the memory to default values c. Resolution: transforming symbolic references from the type into direct references. 3. Initialization: invoking Java code that initializes class variables to their proper starting values. The details of these processes are given Chapter 7, "The Lifetime of a Type." The Bootstrap Class Loader Java virtual machine implementations must be able to recognize and load classes and interfaces stored in binary files that conform to the Java class file format. An implementation is free

to recognize other binary forms besides class files, but it must recognize class files. Every Java virtual machine implementation has a bootstrap class loader, which knows how to load trusted classes, including the classes of the Java API. The Java virtual machine specification doesn't define how the bootstrap loader should locate classes. That is another decision the specification leaves to implementation designers. Given a fully qualified type name, the bootstrap class loader must in some way attempt to produce the data that defines the type. One common approach is demonstrated by the Java virtual machine implementation in Sun's 1.1 JDK on Windows98. This implementation searches a user-defined directory path stored in an environment variable named CLASSPATH. The bootstrap loader looks in each directory, in the order the directories appear in the CLASSPATH, until it finds a file with the appropriate name: the type's simple name plus ".class". Unless the type is part of the unnamed package, the bootstrap loader expects the file to be in a subdirectory of one the directories in the CLASSPATH. The path name of the subdirectory is built from the package name of the type. For example, if the bootstrap class loader is searching for class java.lang.Object, it will look for Object.class in the java\lang subdirectory of each CLASSPATH directory. In 1.2, the bootstrap class loader of Sun's Java 2 SDK only looks in the directory in which the system classes (the class files of the Java API) were installed. The bootstrap class loader of the implementation of the Java virtual machine from Sun's Java 2 SDK does not look on the CLASSPATH. In Sun's Java 2 SDK virtual machine, searching the class path is the job of the system class loader, a user-defined class loader that is created

automatically when the virtual machine starts up. More information on the class loading scheme of Sun's Java 2 SDK is given in Chapter 8, "The Linking Model." User-Defined Class Loaders Although user-defined class loaders themselves are part of the Java application, four of the methods in class ClassLoader are gateways into the Java virtual machine: // Four of the methods declared in class java.lang.ClassLoader: protected final Class defineClass(String name, byte data[], int offset, int length); protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain); protected final Class findSystemClass(String name); protected final void resolveClass(Class c); Any Java virtual machine implementation must take care to connect these methods of class ClassLoader to the internal class loader subsystem. The two overloaded defineClass() methods accept a byte array, data[], as input. Starting at position offset in the array and continuing for length bytes, class ClassLoader expects binary data conforming to the Java class file format--binary data that represents a new type for the running application -- with the fully qualified name specified in name. The type is assigned to either a default protection domain, if the first version of defineClass() is used, or to the protection domain object referenced by the protectionDomain parameter. Every Java virtual machine implementation must make sure the defineClass() method of class ClassLoader can cause a new type to be imported into the method area.

The findSystemClass() method accepts a String representing a fully qualified name of a type. When a user-defined class loader invokes this method in version 1.0 and 1.1, it is requesting that the virtual machine attempt to load the named type via its bootstrap class loader. If the bootstrap class loader has already loaded or successfully loads the type, it returns a reference to the Class object representing the type. If it can't locate the binary data for the type, it throws ClassNotFoundException. In version 1.2, the findSystemClass() method attempts to load the requested type from the system class loader. Every Java virtual machine implementation must make sure the findSystemClass() method can invoke the bootstrap (if version 1.0 or 1.1) or system (if version 1.2 or later) class loader in this way. The resolveClass() method accepts a reference to a Class instance. This method causes the type represented by the Class instance to be linked (if it hasn't already been linked). The defineClass() method, described previous, only takes care of loading. (See the previous section, "Loading, Linking, and Initialization" for definitions of these terms.) When defineClass() returns a Class instance, the binary file for the type has definitely been located and imported into the method area, but not necessarily linked and initialized. Java virtual machine implementations make sure the resolveClass() method of class ClassLoader can cause the class loader subsystem to perform linking. The details of how a Java virtual machine performs class loading, linking, and initialization, with user- defined class loaders is given in Chapter 8, "The Linking Model."

Name Spaces As mentioned in Chapter 3, "Security," each class loader maintains its own name space populated by the types it has loaded. Because each class loader has its own name space, a single Java application can load multiple types with the same fully qualified name. A type's fully qualified name, therefore, is not always enough to uniquely identify it inside a Java virtual machine instance. If multiple types of that same name have been loaded into different name spaces, the identity of the class loader that loaded the type (the identity of the name space it is in) will also be needed to uniquely identify that type. Name spaces arise inside a Java virtual machine instance as a result of the process of resolution. As part of the data for each loaded type, the Java virtual machine keeps track of the class loader that imported the type. When the virtual machine needs to resolve a symbolic reference from one class to another, it requests the referenced class from the same class loader that loaded the referencing class. This process is described in detail in Chapter 8, "The Linking Model."

Bytecode, also known as p-code (portable code), is a term which has been used to denote various forms of instruction sets designed for efficient execution by a software interpreter as well as being suitable for further compilation into machine code. Since instructions are processed by software, they may be arbitrarily complex, but are nonetheless often akin to traditional hardware instructions; virtual stack machines are the most common, but virtual register machines have also been built.

Different parts may often be stored in separate files, similar to object modules, but dynamically loaded during execution. The name bytecode stems from instruction sets which have onebyte opcodes followed by optional parameters. Intermediate representations such as bytecode may be output by programming language implementations to ease interpretation, or it may be used to reduce hardware and operating system dependence by allowing the same code to run on different platforms. Bytecode may often be either directly executed on a virtual machine (i.e. interpreter), or it may be further compiled into machine code for better performance. Unlike human-readable source code, bytecodes are compact numeric codes, constants, and references (normally numeric addresses) which encode the result of parsing and semantic analysis of things like type, scope, and nesting depths of program objects. They therefore allow much better performance than direct interpretation of source code. Execution A bytecode program may be executed by parsing and directly executing the instructions, one at a time. This kind of bytecode interpreter is very portable. Some systems, called dynamic translators, or "just-in-time" (JIT) compilers, translate bytecode into machine language as necessary at runtime: this makes the virtual machine unportable, but doesn't lose the portability of the bytecode itself. For example, Java and Smalltalk code is typically stored in bytecoded format, which is typically then JIT compiled to translate the bytecode to machine code before execution. This introduces a delay before a program is run, when bytecode is compiled to native machine code, but improves

execution speed considerably compared to direct interpretation of the source codenormally by several magnitudes[citation needed]. Because of its performance advantage, today many language implementations execute a program in two phases, first compiling the source code into bytecode, and then passing the bytecode to the virtual machine. Therefore, there are virtual machines for Java, Python, PHP, Forth, and Tcl. The implementation of Perl and Ruby 1.8 instead work by walking an abstract syntax tree representation derived from the source code. Examples

ActionScript executes in the ActionScript Virtual Machine (AVM), which is part of Flash Player and AIR. ActionScript code is typically transformed into bytecode format by a compiler. Examples of compilers include the one built in to Adobe Flash Professional and the one that is built in to Adobe Flash Builder and available in the Adobe Flex SDK. Adobe Flash objects BANCStar, originally bytecode for an interface-building tool but used as a language in its own right. Byte Code Engineering Library C to Java Virtual Machine compilers CLISP implementation of Common Lisp compiles only to bytecode CMUCL and Scieneer Common Lisp implementations of Common Lisp can compile either to bytecode or to native code; bytecode is much more compact Dalvik bytecode, designed for the Android platform, is executed by the Dalvik virtual machine. EiffelStudio for the Eiffel programming language

Emacs is a text editor with a majority of its functionality implemented by its specific dialect of Lisp. These features are compiled into bytecode. This architecture allows users to customize the editor with a high level language, which after compilation into bytecode yields reasonable performance. Embeddable Common Lisp implementation of Common Lisp can compile to bytecode or C code Ericsson implementation of Erlang uses BEAM bytecodes Icon[3] and Unicon[4] programming languages Infocom used the Z-machine to make its software applications more portable. Java bytecode, which is executed by the Java Virtual Machine o ASM o BCEL o Javassist o JMangler LLVM, a modular bytecode compiler and virtual machine Lua, using a register-based virtual machine, also compiles LUAC forms of its scripts for small fast systems that need not include the compiler. m-code of the MATLAB programming language Managed code such as Microsoft .NET Common Intermediate Language, executed by the .NET Common Language Runtime (CLR) O-code of the BCPL programming language Objective Caml (Ocaml) programming language optionally compiles to a compact bytecode form p-code of UCSD Pascal implementation of the Pascal programming language Parrot virtual machine

The R environment for statistical computing offers a byte code compiler through the compiler package, now standard with R version 2.13.0. It is possible to compile this version of R so that the base and recommended packages take advantage of this. Scheme 48 implementation of Scheme using bytecode interpreter Bytecodes of many implementations of the Smalltalk programming language The SPIN interpreter built into the Parallax Propeller Microcontroller SWEET16 Visual FoxPro compiles to bytecode YARV and Rubinius for Ruby.

Java Technology in Small Devices A complete Java technology stack exists today to support embedded devices such as mobile phones.The stack is based on the Java 2 Platform, Micro Edition (J2ME), and includes layers from the Java virtual machine to GUI support.These devices are characterized as small, battery-powered devices with limited, wireless connection tothe Internet. J2ME defines configurations and profiles, which, in combination with a Java virtual machine, make up the Java technology stack.A configuration of J2ME includes a Java virtual machine, as well as the Java programming language libraries that are required as the lowest common denominator of a range of embedded devices.A profile is a layer on top of the configuration that provides additional APIs for a specific class of devices. A particular combination of configuration and profile is appropriate only for specific Java virtual machines.

J2ME fits in with the other editions of Java, J2SE and J2EE.Up to now, small, battery-powered devices are the domain of the KVM and the Mobile Information Device Profile (MIDP), also shown. CLDC HotSpot Implementation is now poised to take the place of the KVM as the high-performance Java virtual machine for the next generation of embedded devices. Implementation Virtual Machine

Figure 1.

The Hotspot Virtual Machine At about the same time that the Spotless project began, a revolutionary Java virtual machine technology called Hotspot was nearing product deployment.Th e Hotspot performance engine was developed to address the perception that Java virtual machine performance was insufficient for many mainstream applications especially on big servers.B y implementing a host of performance enhancing techniques that went beyond innovations like just-in-time (JIT) compilers, the performance of the Java virtual machine increased by an order of magnitude.H otspot technology was rolled out in April 1999.(See the Java HotSpot Virtual Machine Technical White Paper, Sun Microsystems, 2001.) In 2001, these two technology trends converged to inspire the creation of the CLDC HotSpot Implementation virtual machine.Th e feat of creating Java technology enabled consumer devices with KVM and CLDC is impressive, but the perception is

forming in the marketplace that here, as in conventional Java technology, there will ultimately be a need for faster performance.B y applying optimization techniques similar to those used in Hotspot, but using considerably less memory and consuming less power, nearly an order of magnitude improvement can be realized in CLDC-based devices.Demand for Performance The current generation of Java technology-enabled mobile phones have processor and memory requirements that are typical of the original design parameters of the KVM and CLDC.The typical processor is a 16 r o32-bit processor with a oclck speed tsarting from approximately 12-32 MHz, with a memory budget for the Java virtual machine and libraries of about 512 kilobytes.Al though the KVM easily met the footprint requirements of this generation of target devices, the relatively slow processor and the conventional implementation of a bytecode interpreter resulted in performance that was adequate but not impressive.S un Microsystems began to examine the possibility of accelerating performance in the current generation of devices, while looking ahead to the next generation mobile phone designs. Before finalizing the features of CLDC HotSpot Implementation, the development team surveyed key manufacturers to get an accurate picture of the capabilities of current generation and next generation mobile phone designs. Processor and Memory Requirements The following table summarizes processor and memory configurations for next generation mobile phones.(Source : Sun Microsystems customer survey, 2001.)

Key Points Our survey revealed that the following key points are important to manufacturers of current generation and next generation mobile phones: Most of the available memory in a current generation or next generation handset is needed for system software and media capabilities.Thus, the memory footprint of the virtual machine and CLDC libraries must be minimized. Moores Law does not apply to battery life: so far, no exponential expansion of battery capacity with the passage of years has been observed.Every effort must be made to minimize battery consumption for the foreseeable future. The key to executing Java programs at high speeds without draining the battery is keeping the working set of the Java virtual machine inside the on-processor cache. Tunability is key: Implementers must be able to use different size parameters and policies per device. Other Small Consumer Devices Besides mobile phones, the CLDC HotSpot Implementation development team also considered the processor and memory requirements of other devices that potentially belong in the CLDC and MIDP category, such as wireless personal organizers (PDAs) and communicators. Communicator type devices typically have much more memory available than inexpensive mass market handsets, but they are also manufactured in much smaller volume.Al though footprint constraints are much less stringent in this class of device, the next generation of Java virtual machine technology for embedded devices must be appropriate for smaller, high-volume handsets as well. Sun Microsystems, Inc. 7 TABLE 1. Next generation mobile phone capabilities CPU type mostly ARM

CPU speed 30-400 MHz On board RAM 128-384 kB RAM 1-4 MB ROM / Flash 8-24 MB RAM for Java stack mostly under 1 MB

Вам также может понравиться