Univerzitet u Beogradu
Katedra za računarstvo i informatiku

PLATO

Programski jezici i alati

Razrešavanje reflektivnih poziva u GraalVM-u

Motivacija

Kompajler GraalVM Native Image prevodi Java programe u izvršne datoteke pre njihovog pokretanja. Prilikom kompilacije, koristi se pretpostavka zatvorenog sveta: sav kod koji program može da izvrši mora biti dostupan tokom prevođenja. Refleksija otežava analizu dostižnosti koda, jer omogućava pristup klasama, metodama i poljima na osnovu vrednosti koje mogu biti poznate tek tokom izvršavanja. Deo takvih poziva moguće je automatski razrešiti statičkom analizom, čime se smanjuje potreba za ručnim zadavanjem konfiguracije za refleksiju.

Pristup zasnovan na analizi Graal grafovske međureprezentacije zavisi od optimizacija kompajlera. Zbog toga promene u optimizacijama mogu da promene skup automatski razrešenih poziva i utiču na ponašanje generisanog programa. Cilj istraživanja je da pravila razrešavanja budu predvidljiva i nezavisna od kompajlerskih optimizacija.

Analiza Java bajtkoda

U okviru istraživanja razvijeni su proširivi okvir za analizu toka podataka u Java bajtkodu (Stefanović et al., 2025a) i analiza za automatsko razrešavanje reflektivnih poziva (Stefanović et al., 2024), integrisani u sistem GraalVM i detaljno opisani u master radu (Stefanović, 2025b). Analiza prati tok podataka unutar pojedinačnog metoda, prenoseći informacije o poznatim vrednostima kroz stek operanada i lokalne promenljive. Reflektivni poziv razrešava se kada analiza može da utvrdi potrebne vrednosti njegovih argumenata, nakon čega se taj poziv zamenjuje rezultatom njegovog izvršavanja.

Graf toka kontrole sa stanjima steka operanada i lokalnih promenljivih tokom analize Java bajtkoda.
Primer analize bajtkoda: poziv forName u bloku 2 može se razrešiti jer je argument poznat, dok posle spajanja putanja u bloku 3 njegova vrednost nije zaključiva (NAC).

Evaluacija

Rešenje je evaluirano na referentnoj veb aplikaciji Spring PetClinic. Analiza bajtkoda razrešila je 211 reflektivnih poziva, dok je analiza Graal grafova razrešila 222. To predstavlja oko 5% manje razrešenih poziva u ovom eksperimentu, uz nezavisnost od kompilatorskih optimizacija.

Broj razrešenih reflektivnih poziva tokom kompilacije aplikacije Spring PetClinic:

Metod Analiza Graal grafova Analiza bajtkoda
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
Ukupno 222 211

Zahvalnica

Razrešavanje reflektivnih poziva u GraalVM-u se razvija u okviru istraživačke saradnje između Matematičkog fakulteta i kompanije Oracle LLC.

Literatura

  • 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