2009-10-11 21 views
7

Mam sytuację, w której kod użytkownika rzuca IllegalAccessException na polu dostępnym przez odbicie. Tuż przed uzyskaniem dostępu do pola wywołuje się setAccessible(true). Wydaje mi się więc, że ta metoda nie działa prawidłowo.W jakich sytuacjach Java field.setAccessible (true) nie działa?

W jakich sytuacjach by to się stało? Czy to może mieć coś wspólnego z menedżerem bezpieczeństwa?

Oto fragment kodu, który jest przyczyną wyjątek:

private static Field levelField; 
public int getLevel() { 
    try { 
     if (levelField == null) { 
      levelField = MessageInfo.class.getDeclaredField("level"); 
      levelField.setAccessible(true); 
     } 
     return levelField.getInt(this); // <-- IllegalAccessException thrown here 
    } catch (Exception e) { 
     handleException(e); 
    } 
    return ICompilationUnit.NO_AST; 
} 
+1

Wydruk komunikatu wyjątku i stosu byłoby pomocne. – NawaMan

Odpowiedz

4

setAccessible jest udokumentowane, aby rzucić SecurityException. Zauważ, że dokumentacja podaje przypadki, w których zostanie wyrzucony SecurityException, nawet jeśli nie ma obecnie SecurityManager. Oczywiście może również zawieść z powodu wyjątku asynchronicznego: Thread.stop, wyjątku związanego z buforem NIO lub błędu maszyny JVM.

Prawdziwym problemem z tym kodem (poza tym, że używa refleksji) jest to, że istnieje pole, które można ustawić na częściowe zainicjowanie. Powoduje to stan wyścigu (masz zmienną statyczność, dlatego musisz martwić się o wątki (podpowiedź, unikaj zmiennych statyki!)).Inny wątek może wywołać getInt na tym samym Field przed wywołaniem setAccessible. Wygląda na to, że pierwotny pytający się dowiedział, że nie jest też bezpieczny pod względem wyjątków. Dużo bezpieczniejsze i bardziej przejrzyste byłoby ustawienie pola w statycznym inicjatorze.

+0

To ma dla mnie wiele sensu. Dzięki. Nie wiem, czy to jest problem, który widzę, ale wydaje się to możliwe, ponieważ wiem, że wiele wątków zamieszkuje tę część kodu. Ale nawet jeśli to nie jest prawdziwy problem, powinienem zmienić kod. –

0

z Java własnego documentation dla setAccessible():

SecurityException jest podniesione, jeśli flaga jest prawda, ale dostępność do któregokolwiek z elementów tablica wejściowa nie może zostać zmieniona (na przykład, jeśli obiekt elementu jest obiektem klasy Constructor dla klasy klasy). W przypadku takiego SecurityException, dostępność obiektów jest ustawiona na flagę dla elementów tablicy upto (i wykluczając) element, dla którego wystąpił wyjątek; dostępność elementów poza (i tym) elementem, dla którego wystąpił wyjątek, pozostaje niezmieniona.

Niestety nie wspominają nic o o IllegalAccessException.

6

To nie powinno być problemem menedżer bezpieczeństwa - chcesz uzyskać SecurityException lub podklasy.

Kod levelField.getInt(*this*) nie wygląda dobrze ...

Powinieneś przekazując instancję MessageInfo jako parametr.

Dzwonisz z klasy MessageInfo? (dlaczego?!?) lub podklasa MessageInfo? (Próbuje zrobić prywatny pole nadklasą akcie jakby to chroniony? Czy MessageInfo mieć metodę getLevel()? Jeśli tak, to można nazwać super.getLevel() uzyskać wartość zamiast próbować go w ten sposób.)

Jeśli nie MessageInfo lub podklasa, to jest twój problem - masz pole level klasy MessageInfo i próbujesz uzyskać wartość tego pola z bieżącej klasy. Choć należy to rzuca IllegalArgumentExeception zamiast IllegalAccessException ...

jeśli jest to naprawdę „IllegalAccessExeception” - spróbuj umieścić jakiś rejestrowanie wewnątrz tego if (levelField == null) bloku - upewnić się, że naprawdę jest exececuted. Pole jest statyczne - może istnieć jakaś inna instancja lub metoda ustawiająca na nim wartość.

+0

Tak, ta klasa jest podklasą klasy MessageInfo, która jest częścią architektury, z której korzystam. Tak więc pole poziomu jest polem chronionym pakietem MessageInfo bez gettera, a więc jest niedostępne dla mojej podklasy. Ten kod działa poprawnie dla wielu, wielu użytkowników, ale nie jest to ten konkretny. Zastanawiam się więc, czy może być coś osobliwego w konfiguracji tej konkretnej osoby, która sprawia, że ​​połączenie tu nie działa. To właśnie doprowadziło mnie do wniosku, że może to być kierownik ds. Bezpieczeństwa, ale zastanawiam się, czy może być coś jeszcze. –

+0

Być może ten użytkownik ma nowszą/starszą wersję tego frameworka w ścieżce klas? Jeden gdzie MessageInfo.level nie istnieje lub ma inną nazwę? P.S. - Jakie to jest ramy? Może pomóc w rozwiązaniu tego ... – Nate

+0

Być może, ale mało prawdopodobne. Ramy, które opisuję, to JDT Eclipse. A to jest kod, którego używamy od co najmniej 3.3 (zanim pracowałem nad projektem). I przetestowałem to do Eclipse 3.5.1 włącznie. Zgodnie z opisem Tom w zaakceptowanej odpowiedzi, uważam, że może to być problem z wątkami. –

Powiązane problemy