2012-12-28 13 views
9

java.lang.IllegalAccessError: tried to access field ConcreteEntity.instance from class Entityjava.lang.IllegalAccessError: próbowano uzyskać dostęp do pola ConcreteEntity.instance z klasy Entity

Ok, więc tu jest umowa. Próbuję uzyskać dostęp do ConcreteEntity.instance, który jest polem z domyślnym typem dostępu, który znajduje się w domyślnym ClassLoader, a Entity.getInstance jest metodą istniejącą u dziecka ClassLoader.

Pamiętaj, że obie są w tej samej paczce, jednak zostanie przesłana IllegalAccessError. Czy istnieje rozwiązanie tego problemu, które nie wymaga załadowania klasy Entity wewnątrz tego samego ClassLoader jako ConcreteEntity?

0 new #14 <Entity> 
3 dup 
4 aload_0 
5 invokevirtual #18 <Adapter.getInstance> 
8 checkcast #20 <sl> 
11 getfield #24 <sl.d> 
14 invokespecial #25 <Entity.<init>> 
17 areturn 

Kod bajtowy pobrany przez jclasslib w przypadku wygenerowania wyjątku "Po kompilacji".

Dziękuję Gamb za oczyszczenie postu.

+0

Czy modyfikowania klas w czasie wykonywania przy użyciu jakiś kompilator kodu bajtowego? –

+0

Tak, jestem. Ale zmanipulowany kod bajtowy jest bezbłędny. – Justin

+0

Czy próbujesz uzyskać dostęp do pola podklasy wewnątrz superklasy? Myślę, że to nie jest dozwolone. –

Odpowiedz

27

Zobacz my answer do a similar question, chyba w twoim przypadku jest oczywiste, że mamy do czynienia z wieloma classloaders:

JVM uważa klas załadowane z różnych classloaders się w różnych „pakietów wykonania”, nawet jeśli mają ta sama nazwa pakietu. Cytując the jvm spceification, punkt 5.3:

At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.

A w punkcie 5.4.4:

A field or method R is accessible to a class or interface D if and only if any of the following conditions is true:

...

R is either protected or package private (that is, neither public nor protected nor private), and is declared by a class in the same runtime package as D.

+0

Bardzo interesujące. Więc znasz jakąś pracę wokół głowy? Jeśli nie, to albo A) potrzebuję zmienić moją implementację "Niestety przynieś ją do pojedynczego programu ładującego klasy", albo B) wykonaj trochę więcej badań w klasie klasy JVMSpec – Justin

+0

Możesz uczynić pole publicznym, jeśli 'Podmiot' byłby podklasą' ConcreteEntity ", a następnie chronione, powinno również działać.Nie sądzę, że istnieje obejście, ponieważ pojęcie pakietów uruchomieniowych jest ze względów bezpieczeństwa. –

+0

Doceniam twoją odpowiedź. Rzuca światło na to, co się dzieje. Zostało oznaczone jako zaakceptowane. – Justin

1

Javadoc: Zazwyczaj ten błąd jest przechwytywany przez kompilator; ten błąd może wystąpić tylko w czasie wykonywania, jeśli definicja klasy zmieniła się niepoprawnie.

Jak sądzę, podjęto próbę manipulacji klasą, może ładowanie klasy, poświęć trochę czasu na ładowanie obu klas. (W rzadkich przypadkach pomocne może być jawne serialVersionId.)

Jeśli klasy są powiązane (super/podklasa), spróbuj usunąć tę relację za pomocą interfejsu. Ewentualnie użyj wtrysku. To nie jest polecanie/ładowanie klasy dwa razy.

Przepraszam konkretną odpowiedź Nie mogę podać.

+0

Tak, to jest problem z inżynierią niskiego poziomu, jak sądzę. Ale jeśli się nie mylę, nie powinno mieć problemu odwoływanie się do tego pola w normalnych sytuacjach? Niestety, być może będę musiała znaleźć inną trasę z tym, jak mój obfuscator działa w środowisku testowym. – Justin

Powiązane problemy