Діагностика Oracle JVM

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

Усі запити виконуються як DBA в SQL*Plus проти бази даних у стані OPEN. Написано для Oracle 11.2.0.3.2; примітки для 19c / 21c включено там, де поведінка відрізняється.


Діагностичний чеклист — загальна картина

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

#ПеревіркаОб’єкт запитуЩо шукаємо
1.1Банери компонентівALL_REGISTRY_BANNERSПрисутні JServer JAVA Virtual Machine і Oracle Database Java Packages
1.2Реєстр компонентівDBA_REGISTRYJAVAVM і CATJAVA, обидва VALID
1.3Прапор опції рушіяV$OPTIONJava = TRUE
2.1Кількість Java-об’єктівDBA_OBJECTSSYS ≥ ~19 000 JAVA CLASS; нуль рядків INVALID
2.2Пакет DBMS_JAVADBA_OBJECTSУсі записи PACKAGE і PACKAGE BODY зі статусом VALID
2.3Список невалідних об’єктівDBA_OBJECTS + sys.javasnm$no rows selected
2.4Пам’ять Java PoolV$SGASTATПул присутній; вільна пам’ять > 5 МБ
2.5Java-роліDBA_ROLESУсі п’ять основних ролей присутні
Діагностичний чеклист

Частина 1 — Чи встановлено JVM взагалі?

1.1 ALL_REGISTRY_BANNERS

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

SELECT *
FROM all_registry_banners;

Здоровий вивід — обидва рядки мають бути присутні:

JServer JAVA Virtual Machine          Release 11.2.0.3.0 - Production
Oracle Database Java Packages         Release 11.2.0.3.0 - Production

Повний приклад здорової бази даних:

BANNER
-------------------------------------------------------------------
Oracle Database Catalog Views         Release 11.2.0.3.0 - 64bit Production
Oracle Database Packages and Types    Release 11.2.0.3.0 - Production
Oracle Workspace Manager              Release 11.2.0.3.0 - Production
JServer JAVA Virtual Machine          Release 11.2.0.3.0 - Production
Oracle XDK                            Release 11.2.0.3.0 - Production
Oracle Database Java Packages         Release 11.2.0.3.0 - Production
Oracle Expression Filter              Release 11.2.0.3.0 - Production

Приклад бази даних без JVM:

BANNER
-------------------------------------------------------------------
Oracle Database Catalog Views         Release 11.2.0.3.0 - 64bit Production
Oracle Database Packages and Types    Release 11.2.0.3.0 - Production
Oracle Workspace Manager              Release 11.2.0.3.0 - Production
Oracle Expression Filter              Release 11.2.0.3.0 - Production

Якщо відсутній будь-який із банерів JVM — не зупиняйтеся тут. Переходьте до DBA_REGISTRY, щоб визначити: компонент відсутній чи просто невалідний.

1.2 DBA_REGISTRY

DBA_REGISTRY дає повну картину: не лише чи присутній компонент, але й його точний статус. Саме тут ви розрізняєте JVM не встановлено (немає рядків) і JVM встановлено, але пошкоджено (статус INVALID). Різниця важлива — шляхи виправлення відрізняються.

SELECT comp_id, comp_name, version, status
FROM dba_registry;

Здоровий вивід — обидва компоненти присутні та VALID:

COMP_IDCOMP_NAMEVERSIONSTATUS
EXFOracle Expression Filter11.2.0.3.0VALID
OWMOracle Workspace Manager11.2.0.3.0VALID
CATALOGOracle Database Catalog Views11.2.0.3.0VALID
CATPROCOracle Database Packages and Types11.2.0.3.0VALID
JAVAVMJServer JAVA Virtual Machine11.2.0.3.0VALID
XMLOracle XDK11.2.0.3.0VALID
CATJAVAOracle Database Java Packages11.2.0.3.0VALID

Три можливі результати:

  • JAVAVM і CATJAVA відсутні — JVM ніколи не встановлювалася. Потрібне повне встановлення через $ORACLE_HOME/javavm/install/initjvm.sql.
  • JAVAVM або CATJAVA присутні зі статусом INVALID — JVM встановлено, але пошкоджено. Потрібне перевстановлення або цільова рекомпіляція.
  • Обидва присутні та VALID — переходьте до наступних перевірок.

Oracle 19c / 21c — примітка Multitenant: JVM є компонентом рівня PDB в CDB-архітектурах. Виконуйте цей запит, підключившись до цільового PDB, а не до CDB$ROOT. CDB$ROOT не покаже JAVAVM або CATJAVA незалежно від стану JVM у PDB.

1.3 V$OPTION

Цю перевірку легко пропустити, а вона виловлює специфічний клас проблем: об’єкти JVM можуть бути повністю встановлені та валідні, тоді як опція Java-рушія вимкнена на рівні інстансу. У такому стані жоден Java-код не виконається — ви отримаєте лише ORA-29549: class ... has changed, Java session state cleared або подібні помилки рантайму.

SELECT *
FROM v$option
WHERE parameter = 'Java';
PARAMETERVALUE
JavaTRUE

TRUE означає, що опція ліцензована та активна. FALSE означає, що виконання Java вимкнено на рівні рушія — потрібне перелінкування бінарника Oracle із увімкненою опцією Java, що є операцією на рівні ОС хоста бази даних.

Примітка Oracle 19c / 21c: Oracle Database XE та деякі керовані хмарні конфігурації Oracle поставляються з Java = FALSE, навіть якщо схемні об’єкти існують. Якщо ви на керованій платформі — уточніть у свого хмарного провайдера, чи підтримується виконання Java у вашому рівні.


Частина 2 — Інспекція Java-об’єктів

2.1 Кількість Java-об’єктів у SYS

Повне встановлення JVM завантажує десятки тисяч об’єктів Java-класів, ресурсів і даних у SYS. Якщо кількість значно нижча за очікуваний діапазон — встановлення, ймовірно, було перервано або застосовано частково. Використовуйте ці числа як орієнтири, а не жорсткі пороги — рівень патчів дещо впливає на кількість.

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

Орієнтовні пороги для SYS на 11.2.0.3:

OBJECT_TYPEМінімум очікуванийТипове здорове значення
JAVA CLASS~19 000~20 500
JAVA DATA~250~317
JAVA RESOURCE~700~761

Приклад здорового результату:

OWNEROBJECT_TYPESTATUSCOUNT(*)
EXFSYSJAVA CLASSVALID47
EXFSYSJAVA RESOURCEVALID1
SYSJAVA CLASSVALID20 500
SYSJAVA DATAVALID317
SYSJAVA RESOURCEVALID761
SYSJAVA SOURCEVALID2

Будь-які рядки INVALID у секції SYS або кількість об’єктів значно нижче мінімумів — сигнал для запуску повного запиту невалідних об’єктів у розділі 2.3.

Примітка Oracle 19c / 21c: Очікуйте кількість JAVA CLASS у SYS у діапазоні 30 000–40 000 через розширені базові бібліотеки. Значення нижче ~25 000 на стандартній інсталяції 19c потребує розслідування.

2.2 Валідність пакету DBMS_JAVA

DBMS_JAVA — основний PL/SQL-міст до JVM. Якщо тіло пакету невалідне — будь-який код, що його викликає, завершиться помилкою, навіть якщо всі базові Java-об’єкти справні. Ця перевірка також виловлює зламані публічні синоніми, що спричиняють помилки іменного розв’язання на стороні користувача.

SELECT owner, object_name, object_type, status
FROM dba_objects
WHERE object_name LIKE 'DBMS_JAVA%'
   OR object_name LIKE '%INITJVMAUX%'
ORDER BY owner, object_name, object_type;

Очікуваний вивід — кожен рядок має бути VALID:

OWNEROBJECT_NAMEOBJECT_TYPESTATUS
PUBLICDBMS_JAVASYNONYMVALID
PUBLICDBMS_JAVA_DUMPSYNONYMVALID
PUBLICDBMS_JAVA_TESTSYNONYMVALID
SYSDBMS_JAVAPACKAGEVALID
SYSDBMS_JAVAPACKAGE BODYVALID
SYSDBMS_JAVA_DEFINERSPACKAGEVALID
SYSDBMS_JAVA_DEFINERSPACKAGE BODYVALID
SYSDBMS_JAVA_DUMPPACKAGEVALID
SYSDBMS_JAVA_DUMPPACKAGE BODYVALID
SYSDBMS_JAVA_TESTPACKAGEVALID
SYSDBMS_JAVA_TESTPACKAGE BODYVALID

INVALID PACKAGE BODY у SYS при валідній специфікації PACKAGE зазвичай означає часткове застосування встановлення. Повністю відсутній рядок PACKAGE BODY вказує на те, що скрипт встановлення не завершився.

2.3 Перерахування всіх INVALID Java-об’єктів

Цей запит робить join із sys.javasnm$, щоб розкрити короткі внутрішні імена об’єктів, які Oracle використовує всередині, до їхніх повних імен класів. Без цього join’у ви отримаєте беззмістовні скорочені ідентифікатори, які нічого не кажуть про те, який клас зламано.

SELECT owner, NVL(longdbcs, object_name) long_name, object_type, status
FROM dba_objects, sys.javasnm$
WHERE object_type LIKE '%JAVA%'
  AND status <> 'VALID'
  AND short (+) = object_name
ORDER BY owner, long_name, object_type;

Очікуваний результат на здоровій системі:

no rows selected

Якщо рядки з’являються в SYS — повне перевстановлення JVM зазвичай є правильним виправленням; спроба вручну рекомпілювати окремі Java-класи SYS, як правило, перетворюється на нескінченне копання. Для невалідних об’єктів у схемах користувачів цільова рекомпіляція через DBMS_JAVA.compile_class зазвичай достатня.

2.4 Пам’ять Java Pool

Валідні об’єкти та коректне встановлення нічого не варті, якщо Java Pool вичерпано або неправильно налаштовано. Завантаження класів відбувається в рантаймі з цього пулу, і занадто малий пул породжує криптичні помилки — ORA-29553, збої ініціалізації JVM або мовчазну поведінку “клас не знайдено” — замість очевидної помилки пам’яті.

SELECT *
FROM v$sgastat
WHERE pool = 'java pool' OR name = 'free memory'
ORDER BY pool, name;

Приклад здорового результату:

POOLNAMEBYTES
java poolJOXLE15 821 568
java poolfree memory16 906 304
java pooljoxs heap826 560
large poolfree memory8 585 216
shared poolfree memory107 256 528

Як інтерпретувати результат:

УмоваОцінка
Рядки java pool повністю відсутніПул не налаштовано — перевірте параметр JAVA_POOL_SIZE
free memory > 5 МБПрийнятно для легкого використання JVM
free memory < 1 МБВисокий ризик ORA-29553 та збоїв завантаження класів під навантаженням
Загальний java pool < 32 МБЗбільшіть мінімум до 32–64 МБ для будь-якого активного JVM-навантаження

Для інспекції та зміни розміру пулу:

-- Перевірити поточний налаштований розмір
SELECT name, value
FROM v$parameter
WHERE name = 'java_pool_size';

-- Змінити розмір онлайн (лише коли SGA_TARGET не керує пам'яттю автоматично)
ALTER SYSTEM SET java_pool_size = 64M SCOPE=BOTH;

Примітка Oracle 19c / 21c: При Automatic Memory Management (MEMORY_TARGET) або Automatic SGA Management (SGA_TARGET) параметр java_pool_size показуватиме 0 — це очікувано, не проблема. Пул розмірується динамічно менеджером пам’яті. Перевіряйте фактичний розподіл в рантаймі через v$sgastat під репрезентативним навантаженням, а не через значення параметра.

2.5 Java-ролі

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

SELECT role
FROM dba_roles
WHERE role LIKE '%JAVA%'
ORDER BY role;

Очікуваний вивід:

ROLEПримітки
JAVADEBUGPRIVНеобхідна для налагодження Java
JAVAIDPRIVПривілей ідентичності для Java
JAVASYSPRIVСистемний привілей Java
JAVAUSERPRIVСтандартний користувацький привілей Java
JAVA_ADMINАдміністративний привілей Java
JAVA_DEPLOYЗастаріло починаючи з Oracle Database 18c — відсутність на 18c+ є очікуваною

Якщо будь-яка з п’яти основних ролей (JAVAUSERPRIV, JAVASYSPRIV, JAVAIDPRIV, JAVADEBUGPRIV, JAVA_ADMIN) відсутня — встановлення JVM неповне, і необхідно повторно запустити скрипти створення ролей із набору встановлення JVM.

Oracle 19c / 21c — примітка Multitenant: Ролі є локальними для PDB. Виконуйте цю перевірку, підключившись до цільового PDB. Запит із CDB$ROOT покаже неповний або порожній набір незалежно від стану PDB.


Підсумок

Якщо ви пройшли всі вісім перевірок і все зелене — JVM встановлена, валідна та має ресурси для роботи. Якщо знайшли проблеми — найпоширеніші шляхи виправлення:

  • JAVAVM / CATJAVA відсутні в DBA_REGISTRY — необхідне повне встановлення JVM через $ORACLE_HOME/javavm/install/initjvm.sql та суміжні скрипти.
  • Статус INVALID у DBA_REGISTRY або DBMS_JAVA — повторно запустіть скрипти встановлення JVM; розгляньте повне перевстановлення, якщо цільова рекомпіляція не допомагає.
  • Мала вільна пам’ять Java Pool — збільшіть java_pool_size або дайте менеджеру пам’яті більше простору в режимі SGA/AMM.
  • Відсутні ролі — повторно запустіть частину скриптів встановлення JVM, що створює ролі, з $ORACLE_HOME/javavm/install/.

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