Oracle8i
Java Stored Procedures Developer's Guide Release 8.1.5 A64686-01 |
|
To manage Java schema objects, you use the command-line utilities loadjava
and dropjava
. You can write, compile, and partially test and debug Java stored procedures on the client side in popular Java IDEs. Then, you can use loadjava
to upload the resulting Java source, class, and resource files into the RDBMS as schema objects. In addition, you can use dropjava
to drop given Java source, class, and resource schema objects from your schema.
If you create Java class files on the client side, you can use loadjava
to upload them into the RDBMS. Alternatively, you can upload Java source files and let the Aurora JVM compile them. In most cases, it is best to compile and debug programs on the client side, then upload the class files for final testing within the RDBMS.
Loading Java archives (JARs) or ZIP archives is the simplest way to use loadjava
. Archives cannot be schema objects. Therefore, when passed a JAR or ZIP archive, loadjava
loads the archived files individually. For efficiency, files not modified since the last time they were loaded are not reloaded.
Two objects in the same schema cannot define the same class. For example, suppose you define class X
in the file A.java
, load the file, then move the definition of X
to the file B.java
. An attempt to load B.java
will fail. Instead, either drop A.java
or load a new version of it (which no longer defines X
), then load B.java
.
All the classes in a Java program must be loaded before its external references can be resolved. One reason for this requirement is that Java programs have multiple source files because the JDK and other client-side tools require a separate source file for each public class. Another reason is that classes often refer to each other, so name resolution is not possible until all the files have been loaded.
You can use loadjava
to force early resolution. When you specify the option -resolve
, loadjava
uses the SQL ALTER
JAVA
CLASS
... RESOLVE
statement to resolve external references in uploaded Java classes. All references must be resolved before you can use those classes. If you do not specify the option, Oracle executes the SQL ALTER
JAVA
statement implicitly at run time.
If all its references to other classes cannot be resolved, a class is marked invalid. At run time, attempts to load an invalid class throw a ClassNotFound
exception, as required by the Java Language Specification.
Java classes are loaded dynamically at run time. In Sun's JDK, the class loader locates a class by searching sequentially through the list of directories specified by the environment variable CLASSPATH
.
The Aurora JVM uses a similar list called a resolver spec, but instead of directories, it specifies SQL schemas. When the JVM searches for a class corresponding to a Java name, it searches the list of schemas sequentially until a Java schema object matching that name is found. If the object is not found, an error is generated.
Each class has its own resolver spec. For example, class A
's resolver spec lists the schemas to be searched for the classes referenced by A
. Reference lists are maintained by a facility called the resolver.
You can have loadjava
resolve classes or defer resolution until run time. (The resolver runs automatically when the JVM tries to load a class that is marked invalid.) However, it is best to resolve classes before run time to learn of missing classes early.
You can run loadjava
in the following three resolution modes:
-resolve
, loadjava
uploads all classes listed on the command line, marks them invalid, and then resolves them. Use this mode when loading classes that refer to each other, or when reloading isolated classes. Any class that depends on classes not yet loaded remains marked invalid.
-andresolve
, loadjava
resolves each class as it is loaded. In general, this mode is not recommended because it can leave classes that have unresolved references marked valid, causing an error at run time.
-resolve
nor -andresolve
, loadjava
loads files but does not compile or resolve them. Instead, files are compiled (if necessary), and resolved at run time or when the JVM needs their definitions to resolve other classes. If you defer resolution until all classes for an application are loaded, the resolver never has to mark a class invalid because it refers to classes not yet loaded. For that reason, this is the preferred mode.
The option -resolver
binds a resolver spec to the class schema objects that loadjava
creates or replaces. Alternatively, a predefined resolver spec can be bound to class schema objects by the option -oracleresolver
(the default). In most cases, the predefined resolver spec will meet your needs.
A resolver spec lists one or more items, each consisting of a name spec and schema spec in the following form:
"((name_spec schema_spec) [(name_spec schema_spec)] ...)"
A name spec is similar to a name in a Java import statement. It can be a Java class full name, a package name whose final element is the wildcard "*
", or just that wildcard. However, the elements of a name spec must be separated by slashes, not periods. For example, the name spec a/b/*
matches all class names that begin with a.b.
The special name spec, "*
", matches all class names.
A schema spec can be a schema name or the wildcard "-
". The wildcard does not identify a schema; it tells the resolver not to mark a class invalid even if a reference cannot be resolved. (Without the wildcard "-
" in a resolver spec, an unresolved reference invalidates the class and generates an error.) Use wildcard "-"
when you want unresolved references to be detected at run time rather than load time.
When searching for a schema object whose name matches the name spec, the resolver looks in the schema designated by the schema spec. The resolver searches schemas in the order they are listed in the resolver spec. For example,
-resolver "((* SCOTT) (* PUBLIC))"
means "Search for a reference in schema SCOTT
, then in schema PUBLIC
. If a reference is not resolved, mark the referring class invalid and display an error message. In other words, call attention to missing classes". For user SCOTT
, this resolver spec is equivalent to the -oracleresolver
spec.
For another example,
-resolver "((* SCOTT) (* PUBLIC) (* -))"
means "Search for a reference in schema SCOTT
, then in schema PUBLIC
. If the reference is not resolved, mark the referring class valid and do not display an error message. In other words, ignore missing classes".
loadjava
uses the hash table JAVA$CLASS$MD5$TABLE
(called "digest table" from here on) to track the loading of Java schema objects into a given schema. (MD5
refers to RSA Data Security's MD5 Message-Digest Algorithm, which does the hashing.) If you use loadjava
to load a Java schema object, you must use dropjava
to drop the object. Otherwise, the digest table is not updated properly. If that happens, specify the option -force
to bypass the digest table lookup.
The digest table enables loadjava
to skip files that have not changed since they were last loaded. This improves the performance of makefiles and scripts that invoke loadjava
for a whole list of files.
loadjava
detects unchanged files by maintaining a digest table in every schema. The digest table relates a filename to a digest, which is a hash of the file's content. Comparing digests computed for the same file at different times is a fast way to detect a change in the file's content.
For each file it processes, loadjava
computes a digest of the file's content, then looks up the filename in the digest table. If there is a matching entry, loadjava
does not load the file (because a corresponding schema object exists and is up to date). If you specify the option -verbose
, loadjava
shows you the results of its digest table lookups.
Loading a source file creates or updates a Java source schema object and invalidates the class schema objects derived previously from that source file (because they were not compiled from the newly loaded source file). If the class schema objects do not exist, they are created.
To force compilation when you upload a source file, specify the loadjava
option -resolve
. loadjava
displays messages inserted by the compiler into the system database table USER_ERRORS
. For a description of this table, see the Oracle8i Reference.
There are two ways to pass options to the compiler. If you specify the option -resolve
(which might trigger compilation), then you can specify compiler options on the loadjava
command line. You can also set compiler option values in the database table JAVA$OPTIONS
(called "options table" from here on). Then, you can selectively override those settings using loadjava
command-line options.
A row in the options table contains the names of source schema objects to which an option setting applies. You can use multiple rows to set the options differently for different source schema objects.
The compiler looks up options in the options table unless they are specified on the loadjava
command line. If there is no options-table entry or command-line value for an option, the compiler uses the following default value (for the non-default values, see the Oracle8i SQLJ Developer's Guide and Reference):
encoding
=latin1
online
=true // applies only to SQLJ source files
You can get and set options-table entries using the following functions and procedures, which are defined in the supplied package DBMS_JAVA
:
PROCEDURE set_compiler_option( name VARCHAR2, option VARCHAR2, value VARCHAR2); FUNCTION get_compiler_option( name VARCHAR2, option VARCHAR2) RETURNS VARCHAR2; PROCEDURE reset_compiler_option( name VARCHAR2, option VARCHAR2);
The parameter name
is the name of a Java package, the full name of a class, or the empty string. After searching the options table, the compiler selects the row in which name
most closely matches the full name of the schema object. If name
is the empty string, it matches the name of any schema object.
Initially, a schema does not have an options table. To create one, use the procedure dbms_java.set_compiler_option
to set a value. The procedure creates the table if it does not exist. Enclose parameters in single quotes, as shown in the following example:
SQL> dbms_java.set_compiler_option('X.sqlj', 'online', 'false');