Відновлення Oracle JVM

Коли Oracle JVM ламається — вона рідко повідомляє про це чітко. Ви отримуєте каскадні помилки невалідних пакетів, PL/SQL-обгортки, що раптово відмовляються компілюватися, або Java stored procedures, що повертають криптичні помилки ORA-29549 і ORA-29553. Цей гайд охоплює повну послідовність відновлення — від перевірки передумов через перевстановлення самої JVM до відновлення всіх залежних об’єктів та валідації результату.

Написано для Oracle Database 11.2.0.3. Примітки для 19c / 21c включено там, де процедура відрізняється. Усі кроки виконуються як DBA в SQL*Plus, якщо не зазначено інше.

Перш ніж починати: По можливості зробіть холодний бекап або експорт. Процедура перевстановлення JVM перезапускає базу даних у restricted mode та замінює базові системні об’єкти. Вона незворотна без відновлення з резервної копії.


Огляд послідовності відновлення

Виконуйте фази по порядку. Кожна фаза є передумовою для наступної — не пропускайте вперед, якщо знайшли збої.

ФазаЩо охоплюєНеобхідна якщо
1Відновлення CATPROCСтатус CATPROC не VALID в DBA_REGISTRY
2Перевстановлення JVMJAVAVM або CATJAVA відсутні або мають статус INVALID
3Відновлення грантів DBMS_CRYPTOПісля будь-якого перевстановлення JVM або при збоях Java-криптографії
4Відновлення зовнішньої директоріїПісля перевстановлення JVM або коли об’єкти директорій відсутні
5Відновлення Java schema userОбліковий запис Java-користувача заблоковано, відсутній або втратив привілеї
6Перевстановлення кастомних Java-об’єктівJava-класи застосунку невалідні або відсутні
7Функціональне тестуванняЗавжди — виконувати після кожного відновлення

Фаза 1 — Відновлення CATPROC

CATPROC (Oracle Database Packages and Types) є жорсткою залежністю JVM. Якщо він невалідний — скрипти перевстановлення JVM завершаться з помилкою посередині. Виправте спочатку.

Перевірте поточний статус:

SELECT comp_id, comp_name, status
FROM dba_registry
WHERE comp_id = 'CATPROC';

Якщо статус не VALID — виконайте двокроковий виправлення нижче.

Крок 1 — Рекомпіляція невалідних об’єктів

Це швидкий шлях. utlrp.sql паралельно рекомпілює всі невалідні об’єкти в базі даних. Усуває багато проблем із невалідністю CATPROC, спричинених незавершеними патчами або перерваними апгрейдами.

@$ORACLE_HOME/rdbms/admin/utlrp.sql

Після завершення повторно перевірте DBA_REGISTRY. Якщо CATPROC тепер VALID — переходьте до Фази 2. Якщо досі невалідний — переходьте до Кроку 2.

Крок 2 — Перевстановлення каталогу та пакетів

Це відновлює словник даних і всі базові PL/SQL-пакети з нуля. На великих базах даних займає значний час і виводитиме повідомлення про замінювані об’єкти — це очікувано.

@$ORACLE_HOME/rdbms/admin/catalog.sql
@$ORACLE_HOME/rdbms/admin/catproc.sql
@$ORACLE_HOME/rdbms/admin/utlrp.sql

Примітка Oracle 19c / 21c: Скрипти та процедура ідентичні. У CDB-середовищі підключіться до CDB$ROOT як SYSDBA перед запуском — вони працюють на рівні контейнера та застосовуються до PDB відповідним чином.


Фаза 2 — Перевстановлення Oracle JVM

Це ядро відновлення. Процедура монтує базу даних, вимикає кілька фонових процесів, що заважали б заміні JVM, відтворює Java system layer, а потім запускає повні скрипти ініціалізації JVM. База даних має бути перезапущена в рамках цього процесу.

Ця процедура перезапускає базу даних. Погодьте вікно обслуговування. Усі активні сесії будуть завершені.

Крок 1 — Монтування бази даних

Спочатку завершіть роботу бази даних, потім переведіть її в стан mount — не open. Заміна JVM має відбутися до відновлення нормальної роботи.

SHUTDOWN IMMEDIATE;
STARTUP MOUNT;

Крок 2 — Підготовка init-параметрів

Перед відкриттям бази даних вимкніть три налаштування, що інакше заважали б перевстановленню JVM: JIT-компілятор (який намагатиметься компілювати Java-класи під час завантаження), системні тригери (що спрацьовують на DDL і конфліктуватимуть із відтворенням Java system) та процеси черги завдань (які породжують фонові завдання під час встановлення).

ALTER SYSTEM SET java_jit_enabled = FALSE;
ALTER SYSTEM SET "_system_trig_enabled" = FALSE;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 0;

Крок 3 — Відкриття в restricted mode

Відкрийте базу даних, але обмежте доступ лише для DBA-сесій. Це запобігає будь-яким підключенням застосунків до бази даних під час відновлення JVM.

ALTER DATABASE OPEN;
ALTER SYSTEM ENABLE RESTRICTED SESSION;

Крок 4 — Відтворення Java system layer

Цей оператор видаляє та відтворює всю Java system в Oracle. Це еквівалент повного стирання та перевстановлення JVM-рушія. Виконання займає кілька хвилин і не виводить жодного повідомлення — це нормально.

CREATE OR REPLACE JAVA SYSTEM;
/

Після завершення перевірте таблицю Java-об’єктів, щоб підтвердити наявність system layer:

SELECT obj#, name
FROM obj$
WHERE type# IN (28, 29, 30)
   OR namespace = 32;

Ви маєте побачити тисячі рядків. Порожній результат або дуже мала кількість рядків означає, що CREATE OR REPLACE JAVA SYSTEM не завершився успішно — перевірте alert log перед тим як продовжувати.

Крок 5 — Запуск скриптів ініціалізації JVM

Ці скрипти встановлюють усі компоненти JVM у правильному порядку залежностей. Запускайте послідовно і не переривайте. Кожен скрипт може виконуватися кілька хвилин.

-- Базова JVM
@$ORACLE_HOME/javavm/install/initjvm.sql

-- Oracle XML із підтримкою Java
@$ORACLE_HOME/xdk/admin/initxml.sql
@$ORACLE_HOME/xdk/admin/xmlja.sql

-- Java catalog packages
@$ORACLE_HOME/rdbms/admin/catjava.sql

-- Expression Filter (лише Oracle 11g — дивіться примітку нижче)
@$ORACLE_HOME/rdbms/admin/catexf.sql

Примітка Oracle 12c / 19c / 21c: catexf.sql (Expression Filter) було визнано застарілим у 12c, і компонент не існує в 19c/21c. Пропускайте цей скрипт на будь-якій версії від 12c і вище — його запуск призведе до помилок.

Крок 6 — Рекомпіляція всіх невалідних об’єктів

@$ORACLE_HOME/rdbms/admin/utlrp.sql

Крок 7 — Скидання init-параметрів та перезапуск

Відновіть три параметри, що були вимкнені перед встановленням, потім виконайте чисте завершення роботи та нормальний запуск.

ALTER SYSTEM SET java_jit_enabled = TRUE;
ALTER SYSTEM SET "_system_trig_enabled" = TRUE;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 10;

SHUTDOWN IMMEDIATE;

Запустіть базу даних у нормальному режимі (поза SQL*Plus якщо використовується запуск через ОС, або через SQL*Plus):

STARTUP;

Крок 8 — Перевірка відновлення JVM

SELECT comp_id, comp_name, status
FROM dba_registry
WHERE comp_id IN ('JAVAVM', 'CATJAVA');

SELECT count(*), object_type, status
FROM all_objects
WHERE object_type LIKE '%JAVA%'
GROUP BY object_type, status
ORDER BY object_type;

Обидва — JAVAVM і CATJAVA — мають бути VALID, а кількість об’єктів має відповідати референсним значенням із гайду з діагностики Oracle JVM (SYS: ~20 500 JAVA CLASS на 11.2.0.3).

Oracle 19c / 21c — примітка Multitenant: У CDB-середовищі перевстановлення JVM для PDB вимагає підключення безпосередньо до цільового PDB як SYSDBA та запуску initjvm.sql і catjava.sql у контексті цього PDB. Команда CREATE OR REPLACE JAVA SYSTEM також має виконуватися всередині PDB. Зміна _system_trig_enabled є операцією рівня CDB — встановлюйте її з CDB$ROOT перед відкриттям PDB.


Фаза 3 — Відновлення грантів DBMS_CRYPTO

Перевстановлення JVM не завжди зберігає всі гранти привілеїв на системних пакетах. DBMS_CRYPTO є типовою жертвою — будь-який код застосунку, що використовує Java-криптографію або викликає DBMS_CRYPTO напряму зі схем, відмінних від SYS, завершиться помилкою, якщо публічний грант на виконання відсутній.

Перевірте наявність гранту:

SELECT owner, table_name, grantee, privilege
FROM dba_tab_privs
WHERE owner = 'SYS'
  AND table_name = 'DBMS_CRYPTO'
  AND grantee = 'PUBLIC'
  AND privilege = 'EXECUTE';

Якщо рядків не повернуто — відновіть грант:

GRANT EXECUTE ON SYS.DBMS_CRYPTO TO PUBLIC;

Примітка безпеки: Надання гранту на виконання DBMS_CRYPTO для PUBLIC доречне в середовищах, де всі користувачі БД є довіреними обліковими записами застосунків. У мультитенантних або спільних середовищах розгляньте надання лише конкретним ролям або користувачам замість PUBLIC.


Фаза 4 — Відновлення зовнішньої директорії

Об’єкти директорій Oracle — це покажчики рівня бази даних на шляхи файлової системи. Вони використовуються для зовнішніх таблиць, виводу лог-файлів та Java I/O операцій. Після перевстановлення JVM або відновлення бази даних ці об’єкти може знадобитися відтворити.

Крок 1 — Перевірка наявності шляху файлової системи

ls -la /opt/oracle/admin/<db_name>/external_tables/
# Створити якщо відсутній:
mkdir -p /opt/oracle/admin/<db_name>/external_tables/
chown oracle:oinstall /opt/oracle/admin/<db_name>/external_tables/

Крок 2 — Відтворення об’єкта директорії Oracle

-- Перевірити чи вже існує
SELECT directory_name, directory_path
FROM all_directories
WHERE owner = 'SYS';

-- Створити або замінити якщо відсутній/некоректний
CREATE OR REPLACE DIRECTORY LOG_DIR
  AS '/opt/oracle/admin/<db_name>/external_tables';

-- Надати доступ відповідному користувачу або ролі
GRANT READ, WRITE ON DIRECTORY LOG_DIR TO PUBLIC;

Примітка: Замініть <db_name> на фактичне ім’я вашої бази даних. Скоригуйте шлях і назву директорії відповідно до вашого середовища. Перевірте, які схеми фактично потребують доступу, перед тим як надавати грант PUBLIC.


Фаза 5 — Відновлення Java schema user

Якщо ваш застосунок завантажує Java у виділену схему користувача (стандартний підхід для відокремлення Java застосунку від SYS), обліковий запис та привілеї цього користувача потрібно перевірити після будь-якого відновлення JVM. Заблокований обліковий запис або відсутній грант ролі призведе до негайного збою всіх Java-викликів із цієї схеми.

Крок 1 — Створення або розблокування користувача

-- Перевірити чи існує користувач і чи відкритий
SELECT username, account_status
FROM dba_users
WHERE username = 'JAVA_OBJS';

-- Створити якщо відсутній
CREATE USER java_objs IDENTIFIED BY <password>
  DEFAULT TABLESPACE <tablespace_name>;

ALTER USER java_objs QUOTA UNLIMITED ON <tablespace_name>;

-- Розблокувати якщо заблоковано
ALTER USER java_objs ACCOUNT UNLOCK;
ALTER USER java_objs IDENTIFIED BY <password>;

Крок 2 — Відновлення грантів ролей

-- Перевірити наявні гранти ролей
SELECT granted_role
FROM dba_role_privs
WHERE grantee = 'JAVA_OBJS';

-- Відновити необхідні ролі
GRANT JAVASYSPRIV TO java_objs;
GRANT CONNECT TO java_objs;

Примітка Oracle 18c / 19c / 21c: Роль JAVA_DEPLOY визнано застарілою в Oracle Database 18c. Не надавайте її на 18c і пізніших версіях — вона більше не існує. На 11g і раніших версіях вона була необхідна для розгортання Java stored procedures через loadjava.

Крок 3 — Відновлення системних привілеїв

-- Перевірити наявні системні привілеї
SELECT privilege
FROM dba_sys_privs
WHERE grantee = 'JAVA_OBJS';

-- Відновити необхідні привілеї
GRANT CREATE PROCEDURE TO java_objs;
GRANT CREATE TABLE TO java_objs;

Фаза 6 — Перевстановлення кастомних Java-об’єктів

Після відновлення самої JVM та підготовки schema user необхідно повторно розгорнути всі Java-класи застосунку, що були завантажені в базу даних. Загальна схема: видалити старі об’єкти, завантажити з JAR, скомпілювати джерела, розв’язати класи, відтворити PL/SQL wrapper-функції та повторно надати привілеї на виконання.

Крок 1 — Видалення наявних Java-об’єктів зі схеми

Виконується з ОС від імені Oracle OS-користувача. dropjava видаляє всі Java-класи, джерела та ресурси, що були завантажені з вказаного JAR.

dropjava -v -u java_objs/<password> /path/to/your-application.jar

Крок 2 — Завантаження JAR

loadjava -u java_objs/<password> -resolve /path/to/your-application.jar -grant public

Прапор -resolve змушує Oracle перевіряти всі залежності класів під час завантаження, а не відкладати їх. Помилки завантаження набагато простіше діагностувати на цьому етапі, ніж у рантаймі. Прапор -grant public робить завантажені класи доступними для всіх схем — звузьте область, якщо ваш застосунок не потребує публічного доступу.

Крок 3 — Компіляція джерел та розв’язання класів

Якщо ваш JAR містить Java-файли з вихідним кодом (а не лише скомпільовані класи) — скомпілюйте їх явно. Потім розв’яжіть усі класи, щоб підтвердити задоволеність залежностей.

-- Компіляція Java-джерел (якщо застосовно)
ALTER JAVA SOURCE "java_objs"."com/example/YourClass" COMPILE;

-- Розв'язання Java-класів
ALTER JAVA CLASS "java_objs"."com/example/YourClass" RESOLVE;

Перевірте чистоту завантаження:

SELECT object_name, object_type, status
FROM all_objects
WHERE owner = 'JAVA_OBJS'
  AND object_type LIKE '%JAVA%'
ORDER BY object_type, object_name;

Усі рядки мають показувати VALID. Будь-які рядки INVALID вказують на нерозв’язані залежності або помилки компіляції — перевірте USER_ERRORS для деталей.

Крок 4 — Відтворення PL/SQL wrapper-функцій

Java stored procedures викликаються через тонкі PL/SQL wrapper-функції, що відображають SQL-типи на Java-типи. Їх потрібно відтворити, якщо схема була перебудована.

-- Приклад шаблону wrapper
CREATE OR REPLACE FUNCTION java_objs.your_function(input VARCHAR2)
  RETURN VARCHAR2
AS LANGUAGE JAVA
  NAME 'com.example.YourClass.yourMethod(java.lang.String) return java.lang.String';
/

-- Надати доступ до wrapper-функцій
GRANT EXECUTE ON java_objs.your_function TO PUBLIC;

-- Створити публічний синонім для прозорого доступу між схемами
CREATE PUBLIC SYNONYM your_function FOR java_objs.your_function;

Примітка Oracle 19c / 21c: Утиліти loadjava і dropjava все ще існують, але визнані застарілими в 19c і пізніших версіях на користь PL/SQL API DBMS_JAVA.loadjava і DBMS_JAVA.dropjava. Обидва підходи працюють у 19c/21c. Для нових розгортань на 19c+ надавайте перевагу PL/SQL API, оскільки OS-утиліти можуть бути видалені в майбутніх релізах.


Фаза 7 — Функціональне тестування

Не закривайте вікно обслуговування, доки не підтвердите наскрізну роботу виконання Java, а не лише те, що об’єкти мають статус VALID у словнику даних.

Тест 1 — Підтвердження валідності компонентів JVM

SELECT comp_id, comp_name, status
FROM dba_registry
WHERE comp_id IN ('JAVAVM', 'CATJAVA', 'CATPROC');

Усі три мають бути VALID.

Тест 2 — Підтвердження кількості Java-об’єктів

SELECT owner, object_type, status, COUNT(*)
FROM all_objects
WHERE object_type LIKE '%JAVA%'
GROUP BY owner, object_type, status
ORDER BY owner, object_type;

SYS має показувати приблизно 20 500 об’єктів JAVA CLASS (11.2.0.3). Усі рядки мають бути VALID — будь-які рядки INVALID у SYS вимагають повторного запуску utlrp.sql або повторного встановлення JVM.

Тест 3 — Виконання Java з SQL

Викличте одну з Java wrapper-функцій вашого застосунку напряму з SQL. Це підтверджує повний шлях виконання: SQL engine → PL/SQL wrapper → розв’язання Java-класу → виконання JVM → повернення значення.

SELECT your_function('test_input') FROM dual;

Чисте повернення значення підтверджує успіх. ORA-00904 (невалідний ідентифікатор) означає відсутність синоніма або wrapper-функції. ORA-29549 або ORA-29553 означає, що клас досі невалідний або Java Pool недостатній — зверніться до гайду з діагностики для дослідження пам’яті.

Тест 4 — Підтвердження доступності DBMS_JAVA

SELECT owner, object_name, object_type, status
FROM dba_objects
WHERE object_name = 'DBMS_JAVA'
ORDER BY owner, object_type;

І SYS.DBMS_JAVA PACKAGE, і SYS.DBMS_JAVA PACKAGE BODY мають бути VALID. Валідна специфікація з невалідним тілом — поширений режим збою після встановлення.


Поширені патерни збоїв та виправлення

СимптомНайімовірніша причинаДія
ORA-29549 — клас змінивсяJava-клас перезавантажено, але старий стан сесії закешованоВід’єднатися та перепідключитися до всіх сесій; перезапустити пул підключень застосунку
ORA-29553 — клас не знайденоКлас невалідний або Java Pool вичерпаноПовторити Фазу 6; перевірити вільну пам’ять Java Pool у v$sgastat
ORA-00904 — невалідний ідентифікатор при виклику wrapperПублічний синонім відсутній або вказує на неправильну схемуВидалити та відтворити синонім; перевірити наявність GRANT EXECUTE
utlrp.sql завершується, але об’єкти JAVA CLASS залишаються INVALIDНезадоволена залежність класу — referenced клас відсутній або також неваліднийПовторити Фазу 6 з -resolve; перевірити USER_ERRORS для невалідних об’єктів
initjvm.sql завершується з ORA-01017 або помилками привілеївЗапуск не як SYSDBA або restricted session не увімкненоПеревірити рядок підключення — має містити / as sysdba; перевірити активність RESTRICTED SESSION
JVM валідна після відновлення, але знову зламана після наступного перезапуску БДInit-параметри збережено некоректно або SPFILE не оновленоПеревірити що java_jit_enabledJOB_QUEUE_PROCESSES і _system_trig_enabled скинуто з SCOPE=BOTH

Підсумок

Повна послідовність відновлення — CATPROC, перевстановлення JVM, гранти пакетів, об’єкти директорій, schema user, кастомні Java-об’єкти, функціональне тестування — ретельна, але детермінована. Кожна фаза має чіткий критерій успіху перед переходом до наступної. Якщо ви скриптуєте це для автоматизації — ключові перевірки для gating: статус DBA_REGISTRY після кожної фази та живий виклик Java-функції наприкінці, що виконує повний шлях виконання.

Зберігайте копії ваших команд loadjava, DDL wrapper-функцій та операторів надання привілеїв у системі контролю версій. Відновлення JVM о 2-й ночі значно менш болюче, коли перевстановлення кастомних об’єктів — це один скрипт, а не археологія крізь журнали змін.