Oracle8i Java Developer's Guide Release 3 (8.1.7) Part Number A83728-01 |
Library | Service | Contents | Index

## Why Use Java in Oracle8i?

The only reason that you are allowed to write and load Java applications within the database is because it is a safe language. Java has been developed to prevent anyone tampering with the operating system that the Java code resides in. Some languages, such as C, can introduce problems within the database. Java, because of its design, is a safe language to allow within the database.

Although the Java language presents many advantages to developers, providing an implementation of a JVM that supports Java server applications in a scalable manner is a challenge. This section discusses some of these challenges.

- Multithreading

- Automated Storage Management

- Footprint

- Performance

- Dynamic Class Loading

### Multithreading

Multithreading support is often cited as one of the key scalability features of the Java language. Certainly, the Java language and class libraries make it simpler to write multithreaded applications in Java than many other languages, but it is still a daunting task in any language to write reliable, scalable multithreaded code.

As a database server, Oracle8i efficiently schedules work for thousands of users. The Oracle8i Aurora JVM uses the facilities of the RDBMS server to concurrently schedule Java execution for thousands of users. Although Oracle8i supports Java language level threads required by the Java language specification (JLS) and Java Compatibility Kit (JCK), using threads within the scope of the database will not increase your scalability. Using the embedded scalability of the database eliminates the need for writing multithreaded Java servers. You should use the database's facilities for scheduling users by writing single-threaded Java applications. The database will take care of the scheduling between each application; thus, you achieve scalability without having to manage threads. You can still write multithreaded Java applications, but multiple Java threads will not increase your server's performance.

One difficulty multithreading imposes on Java is the interaction of threads and automated storage management, or garbage collection. The garbage collector executing in a generic JVM has no knowledge of which Java language threads are executing or how the underlying operating system schedules them.

- Non-Oracle8i model--A single user maps to a single Java language level thread; the same single garbage collector manages all garbage from all users. Different techniques typically deal with allocation and collection of objects of varying lifetimes and sizes. The result in a heavily multithreaded application is, at best, dependent upon operating system support for native threads, which can be unreliable and limited in scalability. High levels of scalability for such implementations have not been convincingly demonstrated.

- Oracle8i JServer model--Even when thousands of users connect to the server and execute the same Java code, each user experiences it as if he is executing his own Java code on his own Java virtual machine. The responsibility of the Oracle8i JServer is to make use of operating system processes and threads, using the scalable approach of the Oracle RDBMS. As a result of this approach, the JVM's garbage collector is more reliable and efficient because it never collects garbage from more than one user at any time. Refer to "Threading in JServer" for more information on the thread model implementation in JServer.

### Automated Storage Management

Garbage collection is a major feature of Java's automated storage management, eliminating the need for Java developers to allocate and free memory explicitly. Consequently, this eliminates a large source of memory leaks that commonly plague C and C++ programs. There is a price for such a benefit: garbage collection contributes to the overhead of program execution speed and footprint. Although many papers have been written qualifying and quantifying the trade-off, the overall cost is reasonable, considering the alternatives.

Garbage collection imposes a challenge to the JVM developer seeking to supply a highly scalable and fast Java platform. Aurora's JVM meets these challenges in the following ways:

- Aurora JVM uses the Oracle8i scheduling facilities, which can manage multiple users efficiently.

- Garbage collection is consistently performant for multiple users because garbage collection is focused on a single user within a single session. The Oracle8i Aurora JVM enjoys a huge advantage because the burden and complexity of the memory manager's job does not increase as the number of users increases. The memory manager performs the allocation and collection of objects within a single session--which typically translates to the activity of a single user.

- Aurora JVM uses different garbage collection techniques depending on the type of memory used. These techniques provide high efficiency and low overhead.

### Footprint

The footprint of an executing Java program is affected by many factors:

- Size of the program itself--how many classes and methods and how much code they contain.

- Complexity of the program--the amount of core class libraries Aurora uses as the program executes, as opposed to the program itself.

- Amount of state Aurora uses--how many objects Aurora allocates, how large they are, and how many must be retained across calls.

- Ability of the garbage collector and memory manager to deal with the demands of the executing program, which is often non-deterministic. The speed with which objects are allocated and the way they are held on to by other objects influences the importance of this factor.

From a scalability perspective, the key to supporting many concurrent clients is a minimum per-user session footprint. Aurora keeps the per-user session footprint to a minimum by placing all read-only data for users, such as Java bytecodes, in shared memory. Appropriate garbage collection algorithms are applied against call and session memories to maintain a small footprint for the user's session. Aurora uses three types of garbage collection algorithms to maintain the user's session memory:

- Generational scavenging for short-lived objects

- Mark and lazy sweep collection for objects that exist for the life of a single call

- Copying collector for long-lived objects--objects that live across calls within a session

### Performance

JServer performance is enhanced by implementing a native compiler.

#### How Native Compilers Improve Performance

Java executes platform-independent bytecodes on top of a JVM, which in turn deals with the specific hardware platform. Anytime you add levels within software, your performance is degraded. Because Java requires going through an intermediary to interpret platform-independent bytecodes, a degree of inefficiency exists for Java applications that does not exists within a platform-dependent language, such as C. To address this issue, several JVM suppliers create native compilers. Native compilers translate Java bytecodes into platform-dependent native code. This eliminates the interpreter step and improves performance. The following describes two methods for native compilation:

Compiler | Description
--- | ---
Just In Time (JIT) Compilation | JIT compilers quickly compile Java bytecodes to native (platform-specific) machine code during runtime. This does not produce an executable to be executed on the platform; instead, it provides platform-dependent code from Java bytecodes that is executed directly after it is translated. This should be used for Java code that is run frequently, which will be executed at speeds closer to languages such as C.
Static Compilation | Static compilation translates Java bytecodes to platform-independent C code before runtime. Then, a standard C compiler compiles the C code into an executable for the target platform. This approach is more suitable for Java applications that are modified infrequently. This approach takes advantage of the mature and efficient platform-specific compilation technology found in modern C compilers.

Oracle8i uses static compilation to deliver its core Java class libraries, the Aurora/ORB, and JDBC code in natively compiled form. It is applicable across all the platforms Oracle supports, whereas a JIT approach requires low-level, processor-dependent code to be written and maintained for each platform. You can use this native compilation technology with your own Java code. Refer to "Natively Compiled Code" for more information.

### Dynamic Class Loading

Another strong feature of Java is dynamic class loading. The class loader loads classes from the disk (and places them in the JVM-specific memory structures necessary for interpretation) only as they are used during program execution. The class loader locates the classes in the `CLASSPATH` and loads them during program execution. This approach, which works well for applets, poses the following problems in a server environment:

Problem | Description | Solution
--- | --- | ---
Predictability | The class loading operation places a severe penalty on first-time execution. A simple program can cause Aurora to load many core classes to support its needs. A programmer cannot easily predict or determine the number of classes Aurora loads. | Aurora loads classes dynamically, just as with any other Java virtual machine. The same one-time class loading speed hit is encountered. However, because Aurora loads the classes into shared memory, no other users of those classes will cause the classes to load again--they will simply use the same pre-loaded classes.
Reliability | A benefit of dynamic class loading is that it supports program updating. For example, you would update classes on a server, and clients who download the program and load it dynamically see the update whenever they next use the program. Server programs tend to emphasize reliability. As a developer, you must know that every client executes a specific program configuration. You do not want clients to inadvertently load some classes that you did not intend them to load. | Oracle8i separates the upload and resolve operation from the class loading operation at runtime. You upload Java code you developed to the server using the `loadjava` utility. Instead of using `CLASSPATH`, you specify a resolver at installation time. The resolver is analogous to `CLASSPATH`, but allows you to specify the schemas in which the classes reside. This separation of resolution from class loading means you always know what program users execute. Refer to the Oracle8i Java Tools Reference, for details on loadjava and resolvers.

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index