Learn · concepts
JNI Nedir? Modcular İçin Java Yerel Arayüzü
JNI (Java Yerel Arayüzü), JVM'den C/C++ kodunu çağırmak ve geri çağırmak için Java'nın yerleşik köprüsüdür. Minecraft modlarının yerel bir kütüphane yüklemesinin standart yoludur.
JNI'yi basitçe anlatınca ne demektir?
JNI (Java Native Interface), Java'nın iki dünyayı birbirine bağlayan kısmıdır: JVM üzerindeki yönetilen bytecode ve C veya C++ ile yazılmış derlenmiş makine kodu. Bir metot native anahtar kelimesini alır ve gövdesi olmaz, çalışma zamanında JVM bu metodu yüklenen yerel kütüphanedeki eşleşen bir fonksiyona bağlar. Oradan her iki taraf da argümanları ve dönüş değerlerini alışverişi yapar.
Sınır tek yönlü değildir. Yerel fonksiyon bir JNIEnv işaretçisi alır ve bu işaretçi Java'ya geri dönmek için bir geçittir: Java alanlarını okuma ve yazma, Java metotlarını çağırma, nesneler oluşturma ve istisnalar yükseltme için çağrıları açığa çıkarır. Böylece Java'nın dışarı çağırmasına izin veren aynı köprü, C'nin içeri çağırmasına da izin verir.
Bir Minecraft modunun veya istemcisinin neden yerel koda dokunması gerekir?
Çoğu Java JNI'ye ihtiyaç duymaz. Bir mod, JVM'nin tek başına işi yapamadığı durumlarda ona başvurur; genellikle grafikler, ses, işletim sistemi entegrasyonu veya hızlı olması gereken bir rutin. Yerel kütüphane ağır işleri yapar ve JNI onu yüklemenin ve çağırmanın standart yoludur.
Kanıtlanmış bir C kütüphanesini yeniden kullanın
Olgun, yerli bir kod tabanı zaten bu sorunu çözüyor. Java'da yeniden yazmak boşa bir çaba olur, bu yüzden mod buna bağlanıyor.
İşletim sistemine ulaş
Bazı platform özelliklerinin saf Java API'si bulunmamaktadır. Onlara ulaşmanın tek yolu yerel bir çağrı olmaktadır.
Hızlı bir yol aç
Sıkı bir sayısal veya düşük seviyeli rutin, JVM üzerinde bytecode olarak çalışırsa, derlenmiş yerel kod olarak çalışırsa daha hızlı çalışabilir.
Sürücü donanımını ve sürücüleri
JNI, Java tarafına açtığı yerel kütüphanelerin arkasında genellikle işleme, ses ve cihaz erişimi bulunur.
JNI çağrısı uçtan uca nasıl çalışır?
Akış, her platformda aynıdır: yöntemi Java'da bildirin, eşleşen bir C fonksiyonunu paylaşılan bir kütüphaneye derleyin, çalışma zamanında yükleyin, JVM'nin bunları ada göre bağlamasına izin verin ve ardından geçiş yapın. Fonksiyon adları, JVM'nin bunları çözebilmesi için sabit bir kalıba uyar ve oluşturulan bir başlık uygulanacak kesin imzayı belirtir.
| Adım | Olanlar |
|---|---|
| Bildir | Bir Java yöntemi native anahtar kelimesiyle yazılır ve Java tarafında boş bırakılır. |
| Oluştur | Bir C veya C++ fonksiyonu, Windows'ta .dll, Linux'ta .so, macOS'ta .dylib gibi paylaşılan bir kütüphaneye derlenir. |
| Yükle | Java, program çalışırken kütüphaneyi yüklemek için System.loadLibrary'yi çağırır. |
| Bağla | JVM, her native yöntemini, adla bozulmuş bir imza aracılığıyla C fonksiyonuna eşler. |
| Çağır | Java yöntemi çağırır; kontrol yerel koda geçer ve bir sonuçla geri döner. |
JNI size neye mal oluyor?
JNI güçlüdür ve keskin kenarları vardır. Yerel kod, JVM'nin güvenlik ağı dışında çalıştığı için, oradaki bir hata yakalanabilir bir istisna fırlatmak yerine tüm süreci çökertir. Yerel tarafın ayırdığı bellek çöp toplayıcı tarafından görünmez, bu nedenle elle serbest bırakılmadıkça sızıntılar birikir. Her geçiş ek yük getirir ve bu da sınırın içinden sık bir döngü içinde çağırmayı pahalı hale getirir. Ve yerel derlemeler platforma özeldir: bir Windows .dll dosyası, ayrı bir derleme olmadan Linux'ta yüklenemez.
Neler aldığı
- Mevcut C ve C++ kütüphanelerine doğrudan erişim
- JVM'nin ulaşamadığı işletim sistemi ve donanım özelliklerine bir yol
- En çok kullanılan rutinler için yerel hızda yürütme
Maliyeti ne kadardır
- Yerel bir çöküş tüm JVM'yi etkileyebilir.
- Çöp toplayıcı desteği olmadan manuel bellek yönetimi.
- Bakımını ve dağıtımını yapmak için platforma özel derlemeler.
- Sık kullanılan döngülerde sınırları aşan ek yük
JNI ve Yabancı Fonksiyon ve Bellek API'si
JNI orijinal mekanizmadır, ancak artık tek seçenek değil. Yeni Java sürümleri, daha az ek kodla ve daha sıkı güvenlik garantileriyle yerel kodu çağırmak üzere tasarlanmış Yabancı Fonksiyon ve Bellek (FFM) API'sini içerir. JNI, her yerde olduğu ve kapsamlı bir şekilde anlaşıldığı için mevcut araç zincirlerinde hâlâ baskın durumdadır.
| JNI | FFM API | |
|---|---|---|
| Yaş | Orijinal, Java'nın başlarında beri mevcut | Modern, son sürümlerde eklendi |
| Ek Kod | Üretilen başlıklar, adları değiştirilmiş C fonksiyonları | Java'da tanımlanan yöntem tanıtıcıları, ara C kodu yok |
| Bellek Güvenliği | Manuel; hatalar JVM'yi bozabilir | Daha güçlü kontrollerle sınırlı segmentler |
| Benimsenme | Mevcut kütüphanelerde yaygın | Artan, yeni kod tabanlarında |
Sıkça Sorulan Sorular
Yerleşmiş durumda. JNI, JDK ve JVM ile birlikte gelir, bu nedenle Java tarafı ek bir şeye ihtiyaç duymaz. Yerel kısmı derlemek için her hedef platform için hala bir C veya C++ araç zinciri gereklidir.
Hayır. Java kısmı taşınabilirliğini koruyor, ancak yerel bir kütüphane tek bir işletim sistemi ve CPU için derleniyor. Platformlar arası dağıtım, ayrı bir .dll, .so ve .dylib oluşturup paketlemek anlamına geliyor.
Hayır, JNI orijinal mekanizmadır. Son Java sürümleri Foreign Function ve Memory API'sini eklerken, bu API daha güvenli olmayı ve daha az kod tekrarını hedeflese de, JNI yaygın olarak kullanılıyor ve iyi anlaşılıyor.
JVM bir şeyi doğrudan yapamadığında (bir GPU veya ses arka planıyla iletişim kurmak, yalnızca platforma özgü bir API'yi çağırmak veya performans açısından kritik bir rutin çalıştırmak gibi), bir mod yerel bir kütüphane yükler ve JNI aracılığıyla buna çağrı yapar.
Built by people who actually read the JVM internals.