In Oracle Database, you can store and execute Java code directly in the database using Oracle Java Virtual Machine (OJVM). You can take your Java code, put it into the database and execute it. Now your code sits right next to the data, and you can get some amazing benefits.
But it comes at a price:
- You need more time to patch and upgrade the database because OJVM adds another component to the database. There are simply more things to change, and OJVM is one of the components that takes the longest to patch or upgrade.
- Rolling patch installation on a RAC database is not as smooth as without on Oracle Database 19c. As of Oracle Database 21c, it works very smoothly.
- Following a least-privilege principle, remove it if you don’t need it. Check the Critical Patch Updates, and you will sometimes find Java VM listed as a component with a vulnerability. You can of course, apply a security fix, but if you remove OJVM completely, you are less exposed.
It’s really great if you are using OJVM; it has awesome functionality. But if you don’t, consider removing it. When I talk to customers, the big question is often:
How do I know if it is in use in my database?
Setting Things Straight
First, this blog post is about using OJVM: Java code in the database. Often, people mistakenly think they use OJVM because they have a Java application connecting to the database. They don’t. Having a Java application connecting to the database and using OJVM are two completely different things.
OJVM is often also referred to as:
- JAVAVM
- JServer JAVA Virtual Machine
Is OJVM Installed?
You can check if the OJVM component is installed in the database:
SQL> select con_id, comp_id, comp_name, version, status
from cdb_registry
where comp_id='JAVAVM';
If the query returns no rows, then OJVM is not installed.
Has Someone Added Java Code?
You can check if someone has added Java code to the database:
SQL> select con_id, owner, oracle_maintained, status, count(*)
from cdb_objects
where object_type like '%JAVA%'
group by con_id, owner, oracle_maintained, status;
The column ORACLE_MAINTAINED indicates whether a regular user added it. If a user has added Java code, you can use the columns CREATED and LAST_DDL_TIME to find out when it happened. This might help you.
Is Someone Using OJVM Right Now ?
You can query x$kglob
to determine the use of OJVM since the last startup. Refer to RAC Rolling Install Process for the "Oracle JavaVM Component Database PSU/RU" (OJVM PSU/RU) Patches (Doc ID 2217053.1) for details.
The MOS note also shows how to identify which sessions that use OJVM.
OJVM Dependencies
Be advised the following components in Oracle Database depend on OJVM. If you are using one of them, you can’t remove OJVM. The following components use OJVM:
- Spatial Data Option (SDO)
- Oracle XDK (XDK)
- Oracle Multimedia (ORDIM)
Conclusion
Oracle Database is a converged database. You have so many great features directly available in the database. You can do many cool things with them – including OJVM. But if you are not using OJVM or any dependent components in Oracle Database, you can remove OJVM. It will save you time during patch installation and upgrades.
I used an example from oracle-base.com. Visit the article for all the details.
Appendix
Further Reading
- Java Developer’s Guide, About Using Java in Oracle Database, Oracle Database 19c
- SQL Language Reference, CREATE JAVA, Oracle Database 19c
- Oracle JavaVM Component Database PSU/RU (OJVM PSU/RU) Patches (Doc ID 2217053.1), Support Note
- JAVAVM and XML Clean Up in Oracle Database 11.2-19c, mikedietrichde.com
- Java in the database – OJVM non-rolling patches – OJVM Removal, mikedietrichde.com
- OJVM Patching – Oracle Java Virtual Machine, YouTube
- JServer – Java In The Database, oracle-base.com
Test Data
conn / as sysdba
--Query the current status
select comp_id, comp_name, version, status
from dba_registry
where comp_id='JAVAVM';
select con_id, owner, oracle_maintained, status, count(*)
from cdb_objects
where object_type like '%JAVA%'
group by con_id, owner, oracle_maintained, status;
--Shows status in current container and on current instance
--since last startup (MOS Doc ID 2217053.1)
select count(*) from x$kglob where KGLOBTYP = 29 OR KGLOBTYP = 56;
--Create user and small java code
create tablespace appts;
create user appuser identified by appuser;
alter user appuser default tablespace appts;
grant dba to appuser;
conn appuser/appuser
--Thanks to oracle-base.com for a good example
--For further details:
--https://oracle-base.com/articles/8i/jserver-java-in-the-database
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Mathematics" AS
import java.lang.*;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;
public class Mathematics
{
public static int addNumbers (int Number1, int Number2)
{
try
{
int iReturn = -1;
// Connect to the database
Connection conn = null;
OracleDriver ora = new OracleDriver();
conn = ora.defaultConnection();
// Check record exists, and create it if it doesn't
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT " + Number1 + " + " + Number2 + " FROM dual");
if (resultSet.next())
{
iReturn = resultSet.getInt(1);
}
resultSet.close();
statement.close();
conn.close();
return iReturn;
}
catch (Exception e)
{
return -1;
}
}
};
/
show errors java source "Mathematics"
--Query the current status
conn / as sysdba
select con_id, owner, oracle_maintained, status, count(*)
from cdb_objects
where object_type like '%JAVA%'
group by con_id, owner, oracle_maintained, status;
select comp_id, comp_name, version, status
from dba_registry
where comp_id='JAVAVM';
select count(*) from x$kglob where KGLOBTYP = 29 OR KGLOBTYP = 56;
--Expose java code
conn appuser/appuser
CREATE OR REPLACE FUNCTION AddNumbers (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.addNumbers (int, int) return int';
/
--Query the current status
conn / as sysdba
select con_id, owner, oracle_maintained, status, count(*)
from cdb_objects
where object_type like '%JAVA%'
group by con_id, owner, oracle_maintained, status;
select comp_id, comp_name, version, status
from dba_registry
where comp_id='JAVAVM';
select count(*) from x$kglob where KGLOBTYP = 29 OR KGLOBTYP = 56;
--Use Java code
conn appuser/appuser
SELECT addNumbers(1,2)
FROM dual;
--Check which sessions have actively used Java since last startup
--Refer to MOS Doc ID 2217053.1 for the query