Oracle8i Java Developer's Guide
Release 2 (8.1.6)

A81353-01

Library

Product

Contents

Index

Prev Next

5
Security and Performance

This chapter details how to provide security for your Java applications--both for the connection and for the loaded classes--and how to make your application more effective.

The following features are discussed in this chapter:

Security

Security is a large arena that includes network security for the connection, access and execution control of operating system resources or of JVM and user-defined classes, and bytecode verification of imported JAR files from an external source. You should be aware of what type of security you desire for your Java applications. The following sections describe the various security support available for Java applications within Oracle8i.

Network Connection Security

There are two major aspects to network security: authentication and data confidentiality. The type of authentication and data confidentiality is dependent on how you connect to the database--through Net8, JDBC, or distributed object (EJB or CORBA) connection.

Connection Security   Description  

Net8  

The database can require both authentication and authorization before allowing a user to connect to the database. Net8 database connection security can require one or more of the following:

  • Use a username and password for client verification. Each incoming connection into the database has to provide the correct username/password configured within Net8. For more information, see the Net8 Administrator's Guide.

  • Use Advanced Networking Option for encryption, kerberos, or secureId. See the Oracle Advanced Security Administrator's Guide.

  • Use SSL for certificate authentication. See the Oracle Advanced Security Administrator's Guide.

 

JDBC  

JDBC connection security required is similar to the constraints required on a Net8 database connection. In addition to the books listed in the Net8 database connection section, see the Oracle8i JDBC Developer's Guide and Reference.  

Distributed Object  

Encryption and authentication might be required for distributed applications, such as EJB and CORBA. For more information, see the Oracle8i Enterprise JavaBeans and CORBA Developer's Guide.  

Database Contents and JVM Security

Once you are connected to the database, you still must have the correct Java 2 permissions and database privileges to access the resources stored within the database. These resources include the following:

These resources can be protected by the following two methods:

Resource Security   Description  

Database Resource Security  

Authorization for database resources requires that database privileges (not the same as the Java 2 security permissions) are granted to resources. For example, database resources include tables, classes, or PL/SQL packages. For more information, see the Oracle8i Application Developer's Guide - Fundamentals.  

JVM Security  

JServer uses Java 2 security, which uses permissions to protect operating system resources and all loaded classes--both JVM and user-defined classes. Java 2 security is automatically installed upon startup and protects all operating system resources and JVM classes from all users, except JAVA_ADMIN. JAVA_ADMIN can grant permission to other users to access these classes.

All user-defined classes are secured against users from other schemas. You can grant execution permission to other users/schemas through an option on the loadjava command. For more information on setting execution rights when loading the class, see the -grant option discussed in "Loading Classes" or "loadjava".

See "Java 2 Security" for how to manage and modify Java 2 permissions and policies.  

Java 2 Security

Each user or schema must be assigned the proper permissions to access JVM classes and operating system resources. For example, this includes sockets, files, and system properties.

Java 2 security was created to provide a flexible, configurable security for Java applications. With Java 2 security, you can define exactly what permissions on each loaded object a schema or role will have. In 8.1.5, the security provided you the choice of two secure roles:

Because JServer security is based on Java 2 security, you assign permissions to users on a class by class basis.

Java security was created for the non-database world. When you apply the Java 2 security model within the database, certain differences manifest themselves. For example, Java 2 security defines that all applets are implicitly untrusted and all classes within the CLASSPATH are trusted. Within Oracle8i, all classes are loaded within a secure database; thus, no classes are trusted.

The following table briefly describes the differences between Sun Microsystem's Java 2 security and Oracle8i's implementation. This table assumes that you already understand Sun Microsystem's Java 2 security model. For more information, we recommend the following books:

Setting Permissions

As designed in Java 2 security, Oracle8i supports the security classes. Normally, you set the permissions for the code base either through a tool or by editing the security policy file. In Oracle8i, you set the permissions dynamically through DBMS_JAVA procedures. These procedures modify a policy table, which is a new table within the database that exclusively manages Java 2 security permissions.

Two views have been created for you to view the policy table: USER_JAVA_POLICY and DBA_JAVA_POLICY. Both views contain information about granted and restricted permissions. The DBA_JAVA_POLICY view can see all rows within the policy table; the USER_JAVA_POLICY table can only see permissions relevant to the current user. The following is a description of the rows within each view:

Table entry   Description  

Kind  

GRANT or RESTRICT. Shows whether this permission is a positive (GRANT) or negative (RESTRICT) permission.  

Grantee  

The name of the user, schema, or role that the permission is assigned to.  

Permission schema  

The schema that the permission is loaded in.  

Permission type  

The Permission class that you assign. The syntax for the permission name is a string containing the entire class name, such as, java.io.FilePermission.  

Permission name  

The permission name of the assigned Permission class. You use this name when defining the permission. When defining the name for a permission of type PolicyTablePermission, the name can become quite complicated. See "Acquiring Administrative Permission to Update Policy Table" for more information.  

Permission action  

The type of action you grant or restrict for this permission. If no action is appropriate for the permission, supply a null value.  

Status  

ACTIVE or INACTIVE. After granting the permission, you can disable or re-enable the permission. This field shows the status of whether the permission is enabled (ACTIVE) or disabled (INACTIVE).  

Key  

Sequence number you use to identify this row. This number should be supplied when disabling, enabling, or deleting the permission.  

There are two ways to set your permissions:

Fine-Grain Definition for Each Permission

To set individual permissions within the policy table, you must provide the following information:

Parameter   Description  

Grantee  

The name of the user, schema, or role that you want to assign the permission to.  

Permission type  

The Permission class that you are granting permission on. For example, if you are defining access to a file, the permission type would be FilePermission. This parameter requires a fully-qualified name of a class that extends java.lang.security.Permission. If the class is not within SYS, the name should be prefixed by <schema>:. For example, mySchema:myPackage.MyPermission is a valid name for a user generated permission.  

Permission name  

The permission name is defined within the Permission class. Examine the appropriate Permission class for the relevant name. You use this name when the Permission object is created.  

Permission action  

The type of actions that you can specify vary according to the type of permission. For example, FilePermission can have the actions of read or write.  

Key  

Number returned from grant or restrict to use on enable, disable, or delete methods.  

You can grant either Java 2 Permissions or create your own. The Java 2 Permissions are listed in Table 5-1. If you would like to create your own permissions, see "Creating Permissions".

Table 5-1 Permission Types
Permission type  
  • java.util.PropertyPermission

 
  • java.io.SerializablePermission

 
  • java.io.FilePermission

 
  • java.net.NetPermission

 
  • java.net.SocketPermission

 
  • java.lang.RuntimePermission

 
  • java.lang.reflect.ReflectPermission

 
  • java.security.SecurityPermission

 
  • oracle.aurora.rdbms.security.PolicyTablePermission

 
  • oracle.aurora.security.JServerPermission

 

Granting permissions using the DBMS_JAVA package:

procedure grant_permission( grantee varchar2, permission_type varchar2,
permission_name varchar2,
permission_action varchar2 )
procedure grant_permission( grantee varchar2, permission_type varchar2,
permission_name varchar2,
permission_action varchar2, key OUT number)

Granting permissions using Java:

long oracle.aurora.rdbms.security.PolicyTableManager.grant( 
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name,
java.lang.String permission_action);

void oracle.aurora.rdbms.security.PolicyTableManager.grant( 
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name,
java.lang.String permission_action,
long[] key);


Note:

In the Java version of DBMS_JAVA, each method returns the row key identifier, either as a returned parameter or as an OUT variable in the parameter list. In the PL/SQL DBMS_JAVA package, the row key is returned only in the procedure that defines the key OUT parameter. This key is used to enable and disable specific permissions. See "Enabling or Disabling Permissions" for more information.  


Restricting permissions using the DBMS_JAVA package:

procedure restrict_permission( grantee varchar2, permission_type varchar2,
permission_name varchar2,
permission_action varchar2)
procedure restrict_permission( grantee varchar2, permission_type varchar2,
permission_name varchar2,
permission_action varchar2, key OUT number)

Restricting permissions using Java:

long oracle.aurora.rdbms.security.PolicyTableManager.restrict( 
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name,
java.lang.String permission_action);

void oracle.aurora.rdbms.security.PolicyTableManager.restrict( 
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name,
java.lang.String permission_action,
long[] key);

Example 5-1 Granting permissions

Assuming that you have appropriate permissions to modify the policy table, you use the grant_permission method within the DBMS_JAVA package to modify the PolicyTable to allow the user access to the indicated file. In this example, the user, Larry, has PolicyTable modification permission. Within a SQL package, Larry grants permission to read and write a file to the user Dave.

connect larry/larry

REM Grant DAVE permission to read and write the Test1 file.
call dbms_java.grant_permission('DAVE', 
'java.io.FilePermission', '/test/Test1',
'read,write'); REM commit the changes to the PolicyTable commit;

Example 5-2 Restricting permissions

You use the restrict method for specifying exceptions for general rules. You create general rules to grant or restrict access to a larger arena. That is, if you have defined a general rule that no one can read or write for an entire directory, you can use restrict for eliminating one aspect of this rule. In addition, you can override this restriction with a more specific grant. For example, if you want to allow access to all files within the /tmp directory--except for your password file that exists in that directory--you would grant permission for read and write to all files within /tmp and restrict read and write access to the password file. Furthermore, if you want the file owner to still be able to modify the password file, you can grant a more specific permission to allow access to one user, which will override the restriction. JServer security combines all rules to understand who really has access to the password file. The following is the code that implements this example:

  1. Grants everyone read and write permission to all files in /tmp.

  2. Restricts everyone from reading or writing one file in /tmp--password.

  3. Grants Larry explicit permission to read and write the password file.

    connect larry/larry
    
    REM Grant permission to all users (PUBLIC) to be able to read and write
    REM all files in /tmp. call dbms_java.grant_permission('PUBLIC',
    'java.io.FilePermission',
    '/tmp/*',
    'read,write'); REM Restrict permission to all users (PUBLIC) from reading or writing the REM password file in /tmp. call dbms_java.restrict_permission('PUBLIC',
    'java.io.FilePermission',
    '/tmp/password',
    'read,write'); REM By providing a more specific rule that overrides the restriction, REM Larry can read and write /tmp/password. call dbms_java.grant_permission('LARRY',
    'java.io.FilePermission',
    '/tmp/password',
    'read,write'); commit;

The explicit rule for this scenario is as follows:

If the restrict permission implies the request, then for a grant to be effective, the restrict permission must also imply the grant.

Acquiring Administrative Permission to Update Policy Table

After the first initialization for JServer, only a single role--JAVA_ADMIN--is allowed to modify the policy table. The JAVA_ADMIN role is immediately assigned to DBA; thus, if you are assigned to the DBA group, you will automatically take on all JAVA_ADMIN permissions.

In order for you to be able to add permissions to this table, JAVA_ADMIN must grant you administrative permission to change the policy table. JAVA_ADMIN grants your schema update rights for the permission, PolicyTablePermission. This permission defines that your schema can update certain specific permission types. For example, in order for you to add a permission that controls access to a file, you must have a PolicyTablePermission that allows you to add grant or restrict permission on a FilePermission. To grant administrative permission, use the following method within the DBMS_JAVA package.

Granting policy table administrative permissions using DBMS_JAVA:

procedure grant_policy_permission( grantee varchar2, permission_schema varchar2, 
	permission_type varchar2,
permission_name varchar2)
procedure grant_policy_permission( grantee varchar2, permission_schema varchar2, permission_type varchar2,
permission_name varchar2,
key OUT number)

Granting policy table administrative permission using Java:

long oracle.aurora.rdbms.security.PolicyTableManager.grantPolicyPermission(
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name);

void oracle.aurora.rdbms.security.PolicyTableManager.grantPolicyPermission(
java.lang.String grantee,
java.lang.String permission_type,
java.lang.String permission_name,
long[] key);

Parameter   Description  

Grantee  

The name of the user, schema, or role that you want to assign the permission to.  

Permission schema  

The <schema> where the permission class is loaded.  

Permission type  

The Permission class that you are granting permission on. For example, if you are defining access to a file, the permission type would be FilePermission. This parameter requires a fully-qualified name of a class that extends java.lang.security.Permission.  

Permission name  

The permission name is defined within the Permission class. Examine the appropriate Permission class for the relevant name. You use this name when the Permission object is created.  

Row number  

Number returned from grant or restrict to use on enable, disable, or delete methods.  


Note:

When looking at the policy table, the name within the PolicyTablePermission rows contains both the permission type and the permission name, which are separated by a '#'. For example, to grant a user administrative rights for reading a file, the name in the row contains java.io.FilePermission#read. The '#' separates the permission class from the permission name.  


Example 5-3 Granting PolicyTable permission

The following example shows JAVA_ADMIN (as SYS) giving Larry permission to update the PolicyTable for FilePermission. Once this permission is granted, Larry can grant permissions to other users for reading, writing, and deleting files.

REM Connect as SYS, which is assigned JAVA_ADMIN role, to give Larry permission 
REM to modify the PolicyTable connect SYS/SYS REM SYS grants Larry the right to administer permissions for REM FilePermission call dbms_java.grant_policy_permission('LARRY', 'SYS',
'java.io.FilePermission', '*');

Creating Permissions

You can create your own Permission type by performing the following:

1. Create and load the user permission.

2. Grant administrative and action permissions to specified users.

3. Implement security checks for the permission.

1. Create and load the user permission

You can create your own permission by extending the Java 2 Permission class. Any user created permission must extend Permission. The following example creates MyPermission. MyPermission extends BasicPermission, which in turn extends Permission.

package test.larry;
import java.security.Permission;
import java.security.BasicPermission;

public class MyPermission extends BasicPermission {

  public MyPermission(String name) {
    super(name);
  }

  public boolean implies(Permission p) {
    boolean result = super.implies(p);
    return result;
  }
}
2. Grant administrative and action permissions to specified users

When you create a permission, you are designated as owner of that permission. The owner always has administrative rights for the permission. This means that the owner can grant permission, including administrative rights, to other users. Administrative rights permits the user to update the PolicyTable for the user-defined permission. For example, if LARRY creates a permission, MyPermission, only LARRY can invoke grant_policy_permission for himself or another user. This method updates the PolicyTable on who can grant rights to MyPermission. The following code demonstrates this:

REM Since Larry is the user that creates MyPermission, Larry connects to 
REW the database to assign permissions for MyPermission.
connect larry/larry

REM As the owner of MyPermission, Larry grants himself the right to
REM administer permissions for test.larry.MyPermission within the JVM
REM security PolicyTable. Only the owner of the user-defined permission 
REM can grant administrative rights.
call dbms_java.grant_policy_permission('LARRY', 'LARRY',
'test.larry.MyPermission', '*'); REM commit the changes to the PolicyTable commit;

Once you have granted administrative rights, you can grant action permissions for the user created permission. For example, the following SQL grants permission for LARRY to execute anything within MyPermission and DAVE to be able to only execute actions that start with "act.".

REM Since Larry is the user that creates MyPermission, Larry connects to 
REW the database to assign permissions for MyPermission.
connect larry/larry

REM Once able to modify the PolicyTable for MyPermission, Larry grants himself 
REM full permission for MyPermission. Notice that the Permission is prepended 
REM with its owner schema. 
call dbms_java.grant_permission( 'LARRY', 
'LARRY:test.larry.MyPermission', '*', null); REM Larry grants Dave permission to do any actions that start with 'act.*'. call dbms_java.grant_permission ('DAVE', 'LARRY:test.larry.MyPermission', 'act.*', null); REM commit the changes to the PolicyTable commit;
3. Implement security checks for the permission

Once you have created, loaded, and assigned permissions for MyPermission, you must implement the call to SecurityManager for having the permission checked. There are four methods in the following example: sensitive, act, print, and hello. Because of the permissions granted in the SQL example in step 2, the following users can execute methods within the example class:

Enabling or Disabling Permissions

Once you have defined a permission, you can disable it so that it is no longer valid. However, if you decide you want the permission validated again, you can enable the permission. You can delete the permission from the table if you believe that it will never be used again. To delete, you must first disable the permission. If you do not disable the permission, the deletion will not occur.

To disable permissions, you can use either the disable_permission or the revoke method.

Disabling permissions using DBMS_JAVA:

procedure revoke_permission(permission_schema varchar2, 
	permission_type varchar2,
permission_name varchar2,
permission_action varchar2)
procedure disable_permission(key number)

Disabling permissions using Java:

void revoke(String schema, String type, String name, String action);

void oracle.aurora.rdbms.security.PolicyTableManager.disable(long number);

Enabling permissions using DBMS_JAVA:

procedure enable_permission(key number)

Enabling permissions using Java:

void oracle.aurora.rdbms.security.PolicyTableManager.enable(long number);

Deleting permissions using DBMS_JAVA:

procedure delete_permission(key number)

Deleting permissions using Java:

void oracle.aurora.rdbms.security.PolicyTableManager.delete(long number);

Permission Types

Table 5-2 lists the installed permission types. Whenever you want to grant or restrict permission, you must provide the permission type within the DBMS_JAVA method. The permission types with which you control access are the following:

All the Java permission types are documented in Sun Microsystem's Java 2 documentation.


Note:

SYS is granted permission to load libraries that come with Oracle. However, Aurora does not support other users loading libraries, because loading C within the database is insecure. So, you are not allowed to grant permission for loadLibrary.* of RuntimePermission.  


The Oracle-specific permissions, PolicyTablePermission and JServerPermission are described below:

oracle.aurora.rdbms.security.PolicyTablePermission

You use this permission to control who can update the policy table. Once granted the right to update the policy table for a certain Permission type, the user can control another user's access to some resource.

After JServer initialization, only the JAVA_ADMIN role can grant administrative rights for the policy table through PolicyTablePermission. Once it grants this right to other users, these users can in turn update the policy table with their own grant and restrict permissions.

To grant policy table updates, you use the DBMS_JAVA method: grant_policy_permission, as discussed in "Acquiring Administrative Permission to Update Policy Table". Once you have updated the table, you can view either the DBA_JAVA_POLICY or USER_JAVA_POLICY views to see who has been granted permissions.

oracle.aurora.security.JServerPermission

You use this permission to grant and restrict access to Aurora JVM resources. The JServerPermission extends from BasicPermission. The following table lists the names that JServerPermission grants access for:

Permission Name   Description  

LoadClassInPackage.<package_name>  

grants the ability to load a class within the specified package  

Verifier  

grants the ability to turn the bytecode verifier on or off  

Debug  

grants the ability for debuggers to connect to a session  

JRIExtensions  

grants the use of MEMSTAT  

Memory.Call  

grants rights to call certain methods in oracle.aurora.vm.OracleRuntime on call settings  

Memory.Stack  

grants rights to call certain methods in oracle.aurora.vm.OracleRuntime on stack settings  

Memory.SGAIntern  

grants rights to call certain methods in oracle.aurora.vm.OracleRuntime on SGA settings  

Memory.GC  

grants rights to call certain methods in oracle.aurora.vm.OracleRuntime on garbage collector settings  

Initial Permission Grants

When you first initialize JServer, several roles are populated with certain permission grants. The following tables show these roles and their initial permissions:

  1. The JAVA_ADMIN role is given access to modify the policy table for all permissions. All DBAs, including SYS, are granted JAVA_ADMIN. Full administrative rights to update the policy table are granted for the following permissions:

    Permission type  

    java.util.PropertyPermission  

    java.io.SerializablePermission  

    java.io.FilePermission  

    java.net.NetPermission  

    java.net.SocketPermission  

    java.lang.RuntimePermission  

    java.lang.reflect.ReflectPermission  

    java.security.SecurityPermission  

    oracle.aurora.rdbms.security.PolicyTablePermission  

    oracle.aurora.security.JServerPermission  

  2. In addition to the JAVA_ADMIN permissions, SYS is also granted the following permissions:


    Note:

    Within the RuntimePermission grants, there seems to be unnecessary granting of more specific permission for loadlibrary.<package>. The reason for this is to override the restriction given to PUBLIC for loadLibrary.*.  


    Table 5-3 SYS Initial Permissions
    Permission type  Permission name  Action granted 

    oracle.aurora.rdbms.security.PolicyTablePermission  

    *  

    Administrative rights to modify the policy table  

    oracle.aurora.security.JServerPermission  

    *  

    null  

    java.net.NetPermission  

    *  

    null  

    java.security.SecurityPermission  

    *  

    null  

    java.util.PropertyPermission  

    *  

    write  

    java.lang.reflect.ReflectPermission  

    *  

    null  

    java.lang.RuntimePermission  

    *  

    null  

     

    loadLibrary.xaNative  

    null  

     

    loadLibrary.corejava  

    null  

     

    loadLibrary.corejava_d  

    null  

  3. All users are initially granted the following permissions. For the JServerPermission, all users can load classes, except for the list specified in the table. These exceptions are RESTRICT permissions. For more information on RESTRICT permissions, see Example 5-2.

    Table 5-4 PUBLIC Default Permissions
    Permission type  Permission name  Granted action 

    oracle.aurora.rdbms.security.
    PolicyTablePermission
     

    java.lang.RuntimePermission
    loadLibrary.*  

    null  

    java.util.PropertyPermission  

    *  

    read  

     

    user.language  

    write  

    java.lang.RuntimePermission  

     

    null  

     

    exitVM  

    null  

     

    createSecurityManager  

    null  

     

    modifyThread  

    null  

     

    modifyThreadGroup  

    null  

    oracle.aurora.security.JServerPermission  

    loadClassInPackage.* except for loadClassInPackage.java.*, loadClassInPackage.oracle.aurora.*, and loadClassInPackage.jdbc.*  

    null  

    Table 5-5 JAVAUSERPRIV Permissions
    Permission type  Permission name  Action 

    java.net.SocketPermission  

    *  

    connect, resolve  

    java.io.FilePermission  

    <<ALL FILES>>  

    read  

    java.lang.RuntimePermission  

    modifyThreadGroup,
    stopThread,
    getProtectionDomain,
    readFileDescriptor, accessClassInPackage.*, and defineClassInPackage.*  

    null  

    Table 5-6 JAVASYSPRIV Permissions
    Permission type  Permission name  Action 

    java.io.SerializablePermission  

    *  

    no applicable action  

    java.io.FilePermission  

    <<ALL FILES>>  

    read ,write, execute, delete  

    java.net.SocketPermission  

    *  

    accept, connect, listen, resolve  

    java.lang.RuntimePermission  

    createClassLoader  

    null  

     

    getClassLoader  

    null  

     

    setContextClassLoader  

    null  

     

    setFactory  

    null  

     

    setIO  

    null  

     

    setFileDescriptor  

    null  

     

    readFileDescriptor  

    null  

     

    writeFileDescriptor  

    null  

    Table 5-7 JAVADEBUGPRIV Permissions
    Permission type  Permission name  Action 

    oracle.aurora.security.JServerPermission  

    Debug  

    null  

    java.net.SocketPermission  

    *  

    connect, resolve  

General Permission Definition Assigned to Roles

In 8.1.5, JVM security was controlled by granting the roles of JAVASYSPRIV, JAVAUSERPRIV, or JAVADEBUGPRIV to schemas. In the current version, these roles still exist as permission groups. See the previous section, "Initial Permission Grants" for the explicit permissions set for each role. You can set up and define your own collection of permissions. Once defined, you can grant any collection of permissions to any user. That user will then have the same permissions that exist within the role. In addition, if you need additional permissions, you can add individual permissions to either your specified user or role. Permissions defined within the policy table have a cumulative effect. See "Fine-Grain Definition for Each Permission" for information on how to grant permissions to a user or a role.


Note:

The ability to write to properties, granted through the write action on PropertyPermission, is no longer granted to all users. Instead, you must either have JAVA_ADMIN grant you this permission or you can receive this permission by being granted the role of JAVASYSPRIV.  


The following example gives Larry and Dave the following permissions:

Debugging Permissions

A debug role, JAVADEBUGPRIV, was created to grant permissions for running the debugger. The permissions assigned to this role are listed in Table 5-7. In order to have permission to invoke the debug agent, the caller must have been granted JAVADEBUGPRIV or the debug JServerPermission as follows:

REM Granting Dave the ability to debug
grant javadebugpriv to dave;

REM Larry grants himself permission to start the debug agent.
call dbms_java.grant_permission
        ('LARRY', 'oracle.aurora.security.JServerPermission', 'Debug', null);

A debugger provides extensive access to both code and data on the server, but at this time, we envision its use to be restricted to development environments. Refer to the discussion in the section "Debugging Server Applications" for information on using the debugging facilities in this release.

Permission for Loading Classes

In order to load classes, you must have the following permission:

JServerPermission("LoadClassInPackage." + <class_name>)

The class name is the fully qualified name of the class that you are loading.

This excludes loading into system packages or replacing any system classes. Even if you are granted permission to load a system class, JServer prevents you from performing the load. System classes are those classes that are installed with the database.

The following shows the ability of each user after database installation, including permissions and JServer restrictions:

The following example shows how to grant SCOTT permission to load classes into the oracle.aurora.* package:

dbms_java.grant_permission('SCOTT', 'SYS:oracle.aurora.tools.*', null);

Performance

You can increase your Java application performance through one of the following methods:

Natively Compiled Code

All core Java class libraries and Oracle-provided Java code within JServer is natively compiled for greater execution speed. Java classes exist as shared libraries in $ORACLE_HOME/javavm/admin, where each shared library corresponds to a Java package. For example, libjox8java_lang.so on Solaris and libjox8java_lang.dll on Windows/NT hold java.lang classes. Specifics of packaging and naming can vary by platform. The Aurora JVM uses natively compiled Java files internally and opens them, as necessary, at runtime.

Native compilation provides a speed increase ranging from two to ten times the bytecode interpretation. The exact speed increase is dependent on several factors, including:

In general, natively compiled code consumes more memory than interpreted code, by a factor of two to three. Caching in an adaptive optimization technique produces a similar trade-off. This is particularly true when a Java server is executing independent code or stored procedures from thousands of users. Using the JServer's static compilation approach for delivering natively compiled Java code provides a large, consistent performance gain, regardless of the number of users or the code paths they traverse on the server.

Java native compilation technology will be available for your Java code in subsequent releases. In the current JServer release, Java code you load to the server is interpreted; the underlying core classes upon which your code relies (java.lang.*) are natively compiled. Until the native compiler is available for user programs, the net speed benefit of native compilation to your executing program is dependent upon how much native code is traversed, as opposed to interpreted code. The more Java code from core classes and Oracle-provided class libraries you use, the more benefit you will see from native compilation.

Java Memory Usage

The typical and custom database installation process furnishes a database that has been configured for reasonable Java usage during development. However, runtime use of Java should be determined by the usage of system resources for a given deployed application. Resources you use during development can vary widely, depending on your activity. The following sections describe how you can configure memory depending on your performance needs, how to tell how much SGA memory you are using, and what errors denote a Java memory issue:

Configuring Memory Initialization Parameters

You can modify the following database initialization parameters to tune your memory usage to reflect more accurately your application needs:

JServer's unique memory management facilities and sharing of read-only artifacts (such as bytecodes) enables HelloWorld to execute with a per-session incremental memory requirement of only 35 KB. More stateful server applications, such as the Aurora/ORB that CORBA and EJB applications use, have a per-session incremental memory requirement of approximately 200 KB. Such applications must retain a significant amount of state in static variables across multiple calls. Refer to the discussion in the section, "End-of-Call Migration", for more information on understanding and controlling migration of static variables at end-of-call.

Java Pool Memory

Java pool memory is used in server memory for all session-specific Java code and data within the JVM. Java pool memory is used in different ways, depending on what mode the Oracle8i server is running in.

Java pool memory used within a dedicated server

Under dedicated servers, which is probably the case for applications using only Java Stored Procedures, the total required Java pool memory is not much more than 10 MB.

Java pool memory used within a Multi-Threaded Server (MTS)

Under MTS servers, which is the case for applications using CORBA or EJB, this figure could be very large. Java-intensive, multi-user benchmarks could require more than 1 GB. Current size limitations are unknown; however, it is platform dependent.


Note:

If you are compiling code on the server, rather than compiling on the client and loading to the server, you might need a bigger JAVA_POOL_SIZE than the default 20 MB. EJB deployment uses the Java compiler on the server; therefore, it also requires a larger JAVA_POOL_SIZE.  


Displaying Used Amounts of Java Pool Memory

You can find out how much of Java pool memory is being used by viewing the V$SGASTAT table. Its rows include pool, name, and bytes. Specifically, the last two rows show the amount of Java pool memory used and how much is free. The total of these two items equals what you configured in the database initialization file.

SVRMGR> select * from v$sgastat;
POOL        NAME                       BYTES
----------- -------------------------- ----------
            fixed_sga                       69424
            db_block_buffers              2048000
            log_buffer                     524288
shared pool free memory                  22887532
shared pool miscellaneous                  559420
shared pool character set object            64080
shared pool State objects                   98504
shared pool message pool freequeue         231152
shared pool PL/SQL DIANA                  2275264
shared pool db_files                        72496
shared pool session heap                    59492
shared pool joxlod: init P                   7108
shared pool PLS non-lib hp                   2096
shared pool joxlod: in ehe                4367524
shared pool VIRTUAL CIRCUITS               162576
shared pool joxlod: in phe                2726452
shared pool long op statistics array        44000
shared pool table definiti                    160
shared pool KGK heap                         4372
shared pool table columns                  148336
shared pool db_block_hash_buckets           48792
shared pool dictionary cache              1948756
shared pool fixed allocation callback         320
shared pool SYSTEM PARAMETERS               63392
shared pool joxlod: init s                   7020
shared pool KQLS heap                     1570992
shared pool library cache                 6201988
shared pool trigger inform                  32876
shared pool sql area                      7015432
shared pool sessions                       211200
shared pool KGFF heap                        1320
shared pool joxs heap init                   4248
shared pool PL/SQL MPCODE                  405388
shared pool event statistics per sess      339200
shared pool db_block_buffers               136000
java pool   free memory                  30261248
java pool   memory in use                19742720
37 rows selected.

Correcting Out of Memory Errors

Running out of memory while compiling

If you run out of memory while compiling (within loadjava or deployejb), you should see an error:

A SQL exception occurred while compiling: : ORA-04031: unable to allocate  bytes 
of shared memory ("shared pool","unknown object","joxlod: init h", "JOX: ioc_
allocate_pal") 

The cure is to shut down your database and to reset JAVA_POOL_SIZE to a larger value. The mention of "shared pool" in the error message is a misleading reference to running out of memory in the "Shared Global Area". It does not mean you should increase your SHARED_POOL_SIZE. Instead, you must increase your JAVA_POOL_SIZE, restart your server, and try again.

Running out of memory while loading

If you run out of memory while loading classes, it can fail silently, leaving invalid classes in the database. Later, if you try to invoke or resolve any invalid classes, you will see ClassNotFoundException or NoClassDefFoundException exceptions being thrown at runtime. You would get the same exceptions if you were to load corrupted class files. You should perform the following:

End-of-Call Migration

Aurora preserves the state of your Java program between calls by migrating all objects reachable from static variables into session space at the end of the call. Session space exists within the client's session to store static variables and objects that exist between calls. Aurora performs this migration operation at the end of every call, without any intervention by you.

This migration operation is a memory and performance consideration; thus, you should be aware of what you designate to exist between calls and keep the static variables and objects to a minimum. If you store objects in static variables needlessly, you impose an unnecessary burden on the memory manager to perform the migration and consume per-session resources. By limiting your static variables to only what is necessary, you help the memory manager and improve your server's performance.

To maximize the number of users who can execute your Java program at the same time, it is important to minimize the footprint of a session. In particular, to achieve maximum scalability, an inactive session should take up as little memory space as possible. A simple technique to minimize footprint is to release large data structures at the end of every call. You can lazily recreate many data structures when you need them again in another call. For this reason, the Aurora JVM has a mechanism for calling a specified Java method when a session is about to become inactive, such as at end-of-call time.

This mechanism is the EndOfCallRegistry notification. It enables you to clear static variables at the end of the call and reinitialize the variables using a lazy initialization technique when the next call comes in. You should execute this only if you are concerned about the amount of storage you require the memory manager to store in between calls. It becomes a concern only for more complex stateful server applications you implement in Java.

The decision of whether to null-out data structures at end-of-call and then recreate them for each new call is a typical time and space trade-off. There is some extra time spent in recreating the structure, but you can save significant space by not holding on to the structure between calls. In addition, there is a time consideration because objects--especially large objects--are more expensive to access after they have been migrated to session space. The penalty results from the differences in representation of session, as opposed to call-space based objects.

Examples of data structures that are candidates for this type of optimization include:

Oracle-Specific Support for End-of-Call Optimization

You can register the static variables that you want cleared at the end of the call when the buffer, field, or data structure is created. Within the Oracle-specified oracle.aurora.memoryManager.EndOfCallRegistry class, the registerCallback method takes in an object that implements a Callback object. The registerCallback object stores this object until the end of the call. When end-of-call occurs, Aurora invokes the act method within all registered Callback objects. The act method within the Callback object is implemented to clear the user-defined buffer, field, or data structure. Once cleared, the Callback is removed from the registry.


Note:

If the end of the call is also the end of the session, callbacks are not invoked, because the session space will be cleared anyway.  


The way you use the EndOfCallRegistry depends on whether you are dealing with objects held in static fields or instance fields.

A weak table holds the registry of end-of-call callbacks. If either the Callback object or value are not reachable (see JLS section 12.6) from the Java program, they will both be dropped from the table. The use of a weak table to hold callbacks also means that registering a callback will not prevent the garbage collector from reclaiming that object. Therefore, you must hold on to the callback yourself if you need it--you cannot rely on the table holding it back.

You can find other ways in which end-of-call notification will be useful to your applications. The following sections give the details for methods within the EndOfCallRegistry class and the Callback interface:

EndOfCallRegistry.registerCallback method

The registerCallback method installs a Callback object within a registry. At the end of the call, Aurora invokes the act methods of all registered Callback objects.

You can register your Callback object by itself or with a value object. If you need additional information stored within an object to be passed into act, you can register this object within the value parameter.

public static void registerCallback(Callback thunk, Object value);
public static void registerCallback(Callback thunk);

Parameter   Description  

thunk  

The Callback object to be invoked at end-of-call migration.  

value  

If you need additional information stored within an object to be passed into act, you can register this object within the value parameter. In some cases, the value parameter is necessary to hold state the callback needs. However, most users do not need to specify a value.  

EndOfCallRegistry.runCallbacks method
static void runCallbacks()

The JVM calls this method at end-of-call and calls act for every Callback object registered using registerCallback. You should never call this method in your code. It is called at end-of-call, before object migration and before the last finalization step.

Callback Interface
Interface oracle.aurora.memoryManager.Callback

Any object you want to register using EndOfCallRegistry.registerCallback implements the Callback interface. This interface can be useful in your application, where you require notification at end-of-call.

Callback.act method
public void act(Object value)

You can implement any activity that you require to occur at the end of the call. Normally, this method will contain procedures for clearing any memory that would be saved to session space.




Prev

Next
Oracle
Copyright © 1999 Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index