Универзитет у Београду
Катедра за рачунарство и информатику

ПЛАТО

Програмски језици и алати

Разрешавање рефлективних позива у GraalVM-у

Мотивација

Компајлер GraalVM Native Image преводи Java програме у извршне датотеке пре њиховог покретања. Приликом компилације, користи се претпоставка затвореног света: сав код који програм може да изврши мора бити доступан током превођења. Рефлексија отежава анализу достижности кода, јер омогућава приступ класама, методама и пољима на основу вредности које могу бити познате тек током извршавања. Део таквих позива могуће је аутоматски разрешити статичком анализом, чиме се смањује потреба за ручним задавањем конфигурације за рефлексију.

Приступ заснован на анализи Graal графовске међурепрезентације зависи од оптимизација компајлера. Због тога промене у оптимизацијама могу да промене скуп аутоматски разрешених позива и утичу на понашање генерисаног програма. Циљ истраживања је да правила разрешавања буду предвидљива и независна од компајлерских оптимизација.

Анализа Java бајткода

У оквиру истраживања развијени су прошириви оквир за анализу тока података у Java бајткоду (Stefanović et al., 2025a) и анализа за аутоматско разрешавање рефлективних позива (Stefanović et al., 2024), интегрисани у систем GraalVM и детаљно описани у мастер раду (Stefanović, 2025b). Анализа прати ток података унутар појединачног метода, преносећи информације о познатим вредностима кроз стек операнада и локалне променљиве. Рефлективни позив разрешава се када анализа може да утврди потребне вредности његових аргумената, након чега се тај позив замењује резултатом његовог извршавања.

Граф тока контроле са стањима стека операнада и локалних променљивих током анализе Java бајткода.
Пример анализе бајткода: позив forName у блоку 2 може се разрешити јер је аргумент познат, док после спајања путања у блоку 3 његова вредност није закључива (NAC).

Евалуација

Решење је евалуирано на референтној веб апликацији Spring PetClinic. Анализа бајткода разрешила је 211 рефлективних позива, док је анализа Graal графова разрешила 222. То представља око 5% мање разрешених позива у овом експерименту, уз независност од компилаторских оптимизација.

Број разрешених рефлективних позива током компилације апликације Spring PetClinic:

Метод Анализа Graal графова Анализа бајткода
java.lang.Class
forName(String) 77 76
forName(String, boolean, ClassLoader) 18 12
getField(String) 0 0
getDeclaredField(String) 16 16
getConstructor(Class[]) 5 5
getDeclaredConstructor(Class[]) 5 5
getMethod(String, Class[]) 40 37
getDeclaredMethod(String, Class[]) 20 20
getFields() 2 2
getDeclaredFields() 6 6
getConstructors() 0 0
getDeclaredConstructors() 0 0
getMethods() 1 1
getDeclaredMethods() 6 6
getClasses() 0 0
getDeclaredClasses() 0 0
getNestMembers() 0 0
getPermittedSubclasses() 0 0
getRecordComponents() 0 0
getSigners() 0 0
java.lang.invoke.MethodHandles.Lookup
findClass(String) 0 0
findVirtual(Class, String, MethodType) 2 2
findStatic(Class, String, MethodType) 6 6
findConstructor(Class, MethodType) 0 0
findGetter(Class, String, Class) 0 0
findStaticGetter(Class, String, Class) 0 0
findSetter(Class, String, Class) 0 0
findStaticSetter(Class, String, Class) 0 0
findVarHandle(Class, String, Class) 18 17
findStaticVarHandle(Class, String, Class) 0 0
Укупно 222 211

Захвалница

Разрешавање рефлективних позива у GraalVM-у се развија у оквиру истраживачке сарадње између Математичког факултета и компаније Oracle LLC.

Литература

  • Aleksandar Stefanović, Ivan Ristović, Milena Vujošević Janičić: Constant Folding of Reflective Calls via Static Analysis of Java Bytecode. Proceedings of the 14th Symposium "Mathematics and Applications", 2024. URL
  • Aleksandar Stefanović, Ivan Ristović, Milena Vujošević Janičić: Extensible Java Bytecode Data-Flow Analysis JVMCI Framework. Proceedings of the 15th Symposium "Mathematics and Applications", 2025a. URL
  • Aleksandar Stefanović: Razrešavanje reflektivnih poziva statičkom analizom Java bajtkoda. Masters Thesis, Faculty of Mathematics, University of Belgrade, 2025b. URL