The Java VM is an embedded system within Virtuoso that allows the calling of class Java methods and getting class properties. It uses the JAVA JNI API to interact with the JAVA VM.
At maximum one Java VM will be started on demand. If a function from the Java VM API is called and no JVM is running, one will be started, as required. Since Virtuoso is multithreaded it requires JDK version 1.3 or above in order to make better use of it's multithreading support. If the Java VM is already running the API VSEs attaches the current Virtuoso working thread, if not already attached, as a Java VM thread to the running VM. The Virtuoso worker thread does not automatically detached itself from the Java VM after use, therefore, in order to prevent leaving redundant Virtuoso worker threads being left attached to the Java VM the java_vm_detach() VSE should be used.
The following require access to the Java VM:
If no subsequent JVM VSEs are called after calling java_vm_detach(), the worker thread can still attach to the VM in order to deallocate or copy Java VM class reference values. In order to ensure that the worker thread is properly detached it is advisable to set all the variables that may hold Java VM class reference values to NULL, which deallocates their current value, before calling the java_vm_detach() JVM VSE.
Attaching and detaching Virtuoso worker threads is marked as a debug level message in the Virtuoso Event log, so that these messages can be used to debug the process.
Since the Java language uses a different set of data types than Virtuoso a type mapping system has been established to allow the passage of data to and from Java. All Java simple types are mapped to a corresponding Virtuoso type as follows:
Java Type/Class | Virtuoso Internal Type |
---|---|
boolean | smallint |
char | smallint |
double | double precision |
float | real |
int | integer |
short | integer |
long | integer |
boolean | smallint |
java.lang.String | NVARCHAR |
java.util.Date | DATETIME |
All other Java objects are represented as a special Virtuoso value, which contains a reference to the Java object in the VM memory space. When such a value is returned as a Virtuoso/PL return value or as a result set column, it calls the java.lang.Object.toString() method for the Java VM object it refers to and that result is returned to the calling client.
Arrays are mapped to a Virtuoso vector of their elements. The array handling routines are recursive, so each element may be a Java array or a scalar type.
The above mappings are applied when converting Virtuoso/PL data to Java data as follows:
The above mappings are applied in the opposite direction (Java Data -> Virtuoso/PL data) as follows:
Java Class instances are represented as a Virtuoso/PL variable values using a Java VM Global Reference. Each time such a Virtuoso/PL variable value is created or copied, it adds a Java VM Global Reference. When it is freed, it removes the Java VM global reference, allowing the Java Garbage collector (GC) to free it. Each of the API VSEs create a Java VM local frame upon it's start, and frees it upon exit. This allows for fast deallocation of the local objects created by mapping Virtuoso/PL native values to Java objects.
Each method parameter in the java_new_object()/java_call_method() can be either the value itself or a two-element vector. When it is a two-element vector it's first element is the JNI type signature string, e.g.: for integer - I, for array of integers - [I], for java.lang.String - Ljava/lang/String. The signature is important because the Java VM JNI API needs it in order to find the appropriate constructor/method/property.
The API consists of the following VSEs:
Java classes are hosted in one of two modes:
Java class Permissions are managed by security classes that fall into categories as follows listed with it managing class:
Restricted classes are not allowed any of the above privileges. Virtuoso returns errors that are returned by the security manager if breaches in security are attempted by a hosted Java class.
By default all Java classes are imported/created/hosted in restricted mode. To create Java class based user defined types that are unrestricted you need to use create type syntax with UNRESTRICTED keyword. The import_jar() function can also be used to import classes, its third optional parameter can be used to define the security mode.
New behavior since Virtuoso 3.2 provides these two security modes defaulting to restricted. Prior to this Java classes were hosted in unrestricted mode.
The class Write_file, shown below, will attempt to write to a file on the file system. This class will be used to create a user defined type first in unrestricted mode and then in restricted mode to demonstrate how security exceptions are returned.
Source of Write_file.java:
import java.io.*; public class Write_file { public String write () { String myFile = "foo"; File f = new File(myFile); DataOutputStream dos; try { dos = new DataOutputStream (new BufferedOutputStream(new FileOutputStream (myFile),128)); dos.writeBytes("ABC\n"); dos.flush(); dos.close(); } catch (IOException ioe) { System.out.println("writeFile: caught i/o exception"); } return "OK"; } }
Create the unrestricted type:
create type "Write_file" language JAVA external name 'Write_file' unrestricted METHOD "write" () returns nvarchar external type 'Ljava/lang/String;' external name 'write';
Test calling the method:
SQL> select new Write_file().write(); callret NVARCHAR _________________________________________ OK
Now we want to recreate the type in restricted mode, remembering to drop it first:
drop type DB.DBA.write_file; create type "Write_file" language JAVA external name 'Write_file' METHOD "write" () returns nvarchar external type 'Ljava/lang/String;' external name 'write';
Test calling the method:
SQL> select new Write_file().write(); *** Error 42000: [Virtuoso Driver][Virtuoso Server]JV001: Java exception occurred : java.security.AccessControlException : access denied (java.io.FilePermission foo write) in __udt_method_call:(BIF), <Top Level> at line 1 of Top-Level: select new Write_file().write()
Another way to import the above class is by use the import_jar() such as:
import_jar (NULL, 'Write_file', 1) - will import java classes in unrestricted mode. import_jar (NULL, 'Write_file') - will import java classes in restricted mode.
Previous
CLR & Mono |
Chapter Contents |
Next
Virtuoso Server Extension Interface (VSEI) (C Interface) |