Zagadkowy java.lang.IllegalAccessError

0

Zgodnie z dokumetcją

public class IllegalAccessError
extends IncompatibleClassChangeError

Thrown if an application attempts to access or modify a field, or to call a method that it does not have access to.

Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.

U mnie kompilacja przebiegała bez zarzutu, ale podczas wykonywania wiersz

InputText input = new InputText(this,"Tytuł:",title.getTex`code> rzucał wyjątkiem` 
Exception in thread "AWT-EventQueue-0" java.lang.IllegalAccessError: tried to access class InputText from class Creator

(Klasa InputText to moja klasa narzędziowa dziedzicząca po JDialog). Po zmianie nazwy klasy na InputingText wszystko działa.
Ma ktoś hipotezę wyjaśniającą to zjawisko?

0

Zgaduje: w runtime masz dostępną inną klasę o nazwie InputText a tutaj masz jakiś import z * więc automatycznie jest brana pod uwagę. Jeśli w runtime zostanie załadowana wcześniej niż ta twoja to się posypie. Anyway, uruchom to pod debugerem i zobacz co się tam dokładnie dzieje.

0

Też miałem taki pomysł. Przejrzałem wszystkie jary z .../lib/ext, tylko jeden zawiera klasę InputText (tę właściwą). Kopiowałem też plik InputText.class do katalogu z projektem i uruchamiałem program poleceniem java -cp . ..., nie pomagało.

0

A jesteś pewien że uruchamiasz z tym samym z czym kompilowałeś? Bo może klasę masz tylko jedną ale skompilowałeś jara z nią a teraz kompilujesz swój kod używając zmienionej wersji jako zależności a potem odpalasz korzystajac z tego starego jara?

0

Jara z klasą InputText zmieniłem już dzisiaj z 6 razy.
Skopiowałem klasę InputText do projektu, uruchomiłem program z debuggerem, program nie wszedł do konstruktora tej klasy, w zamian rzucił wyjątkiem. JRE wyraźnie korzysta z jakiejś innej wersji tej klasy. Jak ją wytropić.

1

Strzelam...

Masz smieci w plikach .class - wyczyść projekt. (clean - albo recznie je usun). Potem jeszcze raz kompilacja. A aak nie pomoze to może wrzuc zrodla.

0

Nie mam śmieci. Po skopiowaniu plików na inny komputer program (z InputText) poszedł. Na pierwszym komputerze program uruchomiony poleceniem javaw ... też poszedł (polecenie java ... nadal generuje błąd).

0

Dzisiaj (po restarcie komputera i JVM) objawy takie same: javaw ... działa, java ... rzuca wyjątkiem, uruchomienie w IDE (Eclipse) rzuca wyjątkiem.

0

Odpal na debugu:

Class.forName("twoj.pakiet.InputText").getProtectionDomain().getCodeSource().getLocation()

Wynikiem będzie URL do klasy, która rzeczywiście została wybrana z classpathu przez JVM.

Otwórz teraz znaleziony plik w jakimś dekompilatorze (np. JDecompiler) i sprawdź czy kod który tam widzisz pokrywa się z Twoim w edytorze, czy może jednak w runtimie używasz czegoś nieaktualnego.

0

Zaraz sprawdzę. Ale jak pisałem wcześniej

  • przeszukałem wszystkie jary na dysku i znalazłem tylko jedną klasę InputText,
  • sugerujesz, że polecenia java i javaw korzystają z innego runtimu?
0

Aktualnie kod wygląda tak:

mi.addActionListener(e -> changeTitle()); //mi jest typu JMenuItem
...
    private void changeTitle()
    {
        try
        {
            System.out.println(Class.forName("InputText").getProtectionDomain().getCodeSource().getLocation());
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        InputText input = new InputText(this,"Tytuł:",title.getText());
        input.setVisible(true);
        title.setText(input.getText());        
    }

Po uruchomieniu programu poleceniem java ... na konsoli pojawia się nazwa oczekiwanego przeze mnie jara, a po poleceniu javaw ... nie pojawia się nic - kolejna zagadka. Wie ktoś jak namówić debugger w IDE (Eclipse lub IntelliJ) by skorzystał z polecenia javaw? W ostateczności przemianuję tymczasowo javaw.exe' na java.exe`.

0

javaw nie ma "przypisanej" do siebie konsoli więc nie widzisz tego co jest wrzucane do System.out.

Wywołaj sobie na początku metody changeTitle:

System.setOut(new PrintStream(new FileOutputStream("log.txt",true)));

i sprawdź swój output w pliku.

0

Raczysz żartować. Skoro uruchamiam program poleceniem javaw ... tzn. że wpisuję to polecenie w konsoli i żadna zmiana strumienia wyjściowego nie jest potrzebna.

0

Nie żartuję.

javaw forkuje nowy proces i jego standardowe wyjście nijak nie jest powiązane z Twoją konsolą.

0

W obu przypadkach (java ... i javaw ...) jest ta sama nazwa klasy.

0

Miałem kiedyś podobny przypadek, java ewidentnie widziała klasę pomimo tego, ta była usunięta z projektu. Żadne cleany i rekompilacje nie pomagały. Nie pomagało też ubijanie wszystkich działających JVM, tylko, że w moim przypadku restart OS pomógł.

1 użytkowników online, w tym zalogowanych: 0, gości: 1