yasa dışı yansıtıcı erişim nedir


128

Java 9'da yasadışı yansıtıcı erişim hakkında pek çok soru var.

Şimdi bulamadığım şey, çünkü Google'ın tüm kusuru, hata mesajlarını aşmaya çalışan insanlar, aslında yasadışı yansıtıcı erişimin ne olduğu.

Bu yüzden sorum oldukça basit:

Yasadışı yansıtıcı erişimi ne tanımlar ve hangi koşullar uyarıyı tetikler?

Java 9'da tanıtılan kapsülleme ilkeleriyle bir ilgisi olduğunu, ancak hepsinin nasıl bir arada durduğunu ve hangi senaryoda bir açıklama bulamadığım için uyarıyı neyin tetiklediğini anladım.


Yanıtlar:


56

Modüller ve ilgili paketleri arasındaki erişimlerin anlaşılmasının yanı sıra. Bunun özünün Modül Sisteminde yattığına inanıyorum # Rahat-güçlü-kapsülleme ve soruyu cevaplamaya çalışmak için sadece ilgili kısımlarını seçerdim.

Yasadışı yansıtıcı erişimi ne tanımlar ve hangi koşullar uyarıyı tetikler?

Java-9'a geçişe yardımcı olmak için modüllerin güçlü kapsüllenmesi gevşetilebilir.

  • Bir uygulama, statik erişim sağlayabilir , yani derlenmiş bayt kodu ile.

  • Bir veya daha fazla modülünün bir veya daha fazla paketinin içinde koda açık olmasıyla çalışma zamanı sistemini çağırmak için bir yol sağlayabilir. Tüm adlandırılmamış modüllerde , yani sınıf yolunda kodlama. Çalışma zamanı sistemi bu şekilde çağrılırsa ve bunu yaparak, yansıma API'lerinin bazı çağrıları başarılı olur, aksi takdirde başarısız olurlar.

Bu gibi durumlarda, aslında yansıtıcı bir erişim oluşturdunuz. tamamen modüler bir dünyada bu tür erişimleri yapmanız gerekmediğinden, "yasa dışı" etmiş olursunuz.

Her şey nasıl birbirine bağlı ve hangi senaryoda uyarıyı tetikliyor?

Kapsüllemenin bu gevşemesi, çalışma zamanında --illegal-accessJava9'da varsayılan olarak şuna eşit olan yeni bir başlatıcı seçeneği ile kontrol edilir.permit . permitmod olmasını sağlar

Bu tür herhangi bir pakete yönelik ilk yansıtıcı erişim işlemi, bir uyarının verilmesine neden olur, ancak bu noktadan sonra hiçbir uyarı verilmez. Bu tek uyarı, başka uyarıların nasıl etkinleştirileceğini açıklar. Bu uyarı bastırılamaz.

Modlar, değerlerle yapılandırılabilir debug(mesaj ve bu tür her erişim için yığın izleme), warn(bu tür her erişim için mesaj) vedeny (bu tür işlemleri devre dışı bırakır .


Uygulamalarda hata ayıklanacak ve düzeltilecek birkaç şey şunlar olabilir: -

  • Açıktan --illegal-access=denyhaberdar olmak ve açıktan kaçınmak için çalıştırın böyle bir direktif (dahil bir modül beyanı olmadan başka bir modülden ing paketleri opens) ya da kesin kullanımı --add-opensVM arg.
  • Derlenmiş koddan JDK-dahili API'lere statik referanslar, jdepsşu --jdk-internalsseçenekle araç kullanılarak tanımlanabilir

Yasadışı bir yansıtıcı erişim işlemi tespit edildiğinde verilen uyarı mesajı aşağıdaki forma sahiptir:

WARNING: Illegal reflective access by $PERPETRATOR to $VICTIM

nerede:

$PERPETRATOR söz konusu yansıtıcı işlemi çağıran kodu içeren türün tam nitelikli adı ve varsa kod kaynağı (yani JAR dosyası yolu) ve

$VICTIM çevreleyen türün tam nitelikli adı da dahil olmak üzere erişilen üyeyi tanımlayan bir dizedir

Böyle bir örnek uyarı için sorular: = JDK9: Yasadışı bir yansıtıcı erişim işlemi meydana geldi. org.python.core.PySystemState

Son ve önemli bir not, bu tür uyarılarla karşılaşmamanızı ve gelecekte güvende olmanızı sağlamaya çalışırken, yapmanız gereken tek şey, modüllerinizin bu yasa dışı yansıtıcı erişimleri yapmadığından emin olmaktır. :)


23

Java 9 modül sistemi ile ilgili bulduğum bir Oracle makalesi var

Varsayılan olarak, bir modüldeki bir tip, genel bir tür olmadığı ve siz onun paketini vermedikçe diğer modüller tarafından erişilebilir değildir. Yalnızca açığa çıkarmak istediğiniz paketleri ifşa edersiniz. Java 9 ile bu aynı zamanda yansıma için de geçerlidir.

Https://stackoverflow.com/a/50251958/134894'te belirtildiği gibi , AccessibleObject#setAccessibleJDK8 ve JDK9 arasındaki farklar öğreticidir. Özellikle, JDK9 eklendi

Bu yöntem, C sınıfındaki bir çağırıcı tarafından, aşağıdaki durumlardan herhangi biri varsa, D sınıfını bildiren bir üyeye erişim sağlamak için kullanılabilir:

  • C ve D aynı modülde.
  • Üye halka açıktır ve D, D içeren modülün en azından C içeren modüle ihraç ettiği bir pakette halka açıktır.
  • Üye statik korumalıdır, D içeren modülün en azından C içeren modüle ihraç ettiği bir pakette D herkese açıktır ve C, D'nin bir alt sınıfıdır.
  • D, D'yi içeren modülün en azından C içeren modüle açtığı bir pakette yer alır. Adsız ve açık modüllerdeki tüm paketler tüm modüllere açıktır ve bu nedenle bu yöntem, D adsız veya açık bir modülde olduğunda her zaman başarılı olur.

modüllerin ve dışa aktarılmalarının önemini vurgulayan (Java 9'da)


2
Bu nedenle, bu makaleyi okursam, dışa aktarılan sınıflarda özel özellikleri doğru bir şekilde değiştirirsem tablonun dışında kalır. Yalnızca korumalı ve genel mülkler değiştirilebilir. Şimdi java dahili ihracatı hakkında pek bir şey umurumda değil, daha çok bazen belirli bir değere ayarlanacak özel bir değişkene erişmem gereken 3. parti kitaplıklar hakkında. Kendini bir modül olarak tanımlasaydı, bu şemada artık mümkün olmazdı, bu doğru mu?
Tschallacka

1
Doğrudan bununla ilgili deneyimim yok, ancak benim anlayışım bu ve başka bir yerde bahsedilen makalenin ( jaxenter.com/jdk-9-replace-permit-illegal-access-134180.html ) yanı sıra, dava. –illegal-access=permit
JVM'nizi

1
Bu, modül yoluna gitmeye karar verdiklerinde, bazı şeyler için işleri yoluna koymaya çalışırken işleri daha ilginç hale getirecek. Önümüzdeki süper eğlenceli zamanlar.
Tschallacka

1
Çeşitlifun
ptomli

Diğer cevabı daha fazla açıklama sağladığı ve soruya daha çok cevap verdiği için kabul ettim ama ne yazık ki iki cevabı kabul edemiyorum.
Tschallacka

13

Sadece bak setAccessible()privateAlanlara ve yöntemlere erişmek için kullanılan yönteme :

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-

https://docs.oracle.com/javase/9/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-

Şimdi bu yöntemin işe yaraması için gereken çok daha fazla koşul var. Neredeyse tüm eski yazılımları kırmamasının tek nedeni, düz JAR'lardan otomatik olarak oluşturulan modüllerin çok izin vericidir (herkes için her şeyi açın ve dışa aktarın).


1

Add-open seçeneğiyle gitmek istiyorsanız, burada hangi modülün hangi paketi sağladığını bulmak için bir komut var ->

java --list-modules | tr @ " " | awk '{ print $1 }' | xargs -n1 java -d

modülün adı @ ile gösterilirken, onsuz paketlerin adı

NOT: JDK 11 ile test edildi

ÖNEMLİ: Açıkçası paketin sağlayıcısının yasadışı erişimi yapmamasından daha iyidir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.