2009-04-23 10 views
17

Czy w Javie możliwe jest tworzenie definicji klasy w locie podczas działania aplikacji, a następnie tworzenie obiektu tej klasy?Definiowanie klasy podczas działania aplikacji Java

Na przykład uruchomiona aplikacja odczytałaby w pliku tekstowym, który zawiera listę członków klasy do uwzględnienia w nowej klasie. Aplikacja definiuje definicję klasy na podstawie listy członków, a następnie insantiate.

+25

W ten sposób powstaje SkyNet. – TheTXI

+7

Jeśli SkyNet został napisany w Javie, wymagałoby to zdecydowanie za dużo pamięci, aby kiedykolwiek było zagrożeniem. – Pesto

+4

SkyNet zbudowałoby sobie większy klaster do działania. Fakt, że jest napisany na Jawie, miałby sens, ponieważ zarówno SkyNet, jak i Java staną się końcem ludzkości. – TheTXI

Odpowiedz

11

Tak, jest to możliwe, teoretycznie Twój plik klasy to kod bajtowy, który jest na końcu tablicą bajtów! możesz następnie użyć metody defineClass (String, byte [], int, int), aby uzyskać instancję Class, której można użyć do tworzenia instancji obiektów za pomocą odbicia.

W praktyce można użyć czegoś takiego jak CGLib lub javaassist.

Można również wykorzystać długą drogę generowania kodu Java w pliku, wywoływanie kompilatora, a następnie ładowanie pliku.

1

Możesz to zrobić, pisząc kod nowej klasy do pliku, a następnie wywołując kompilator Java w tym pliku i używając modułu ładującego klasy, aby dynamicznie załadować tę klasę do uruchomionej aplikacji. Apache Tomcat robi to dla swoich stron JSP; pobiera kod, wprowadza pewne zmiany, owija go w blok try/catch w środku klasy, który następnie zapisuje do systemu plików, kompiluje go i używa modułu ładującego klasy, aby uzyskać i pozwać go, aby obsługiwał żądania.

2

Można dynamicznie wygenerować klas używając ASM

0

może trochę overkill The Apache BCEL (Byte Code Library Inżynieria) mogą być wykorzystywane do tworzenia class plików podczas wykonywania.

Chociaż sam tego nie wypróbowałem, można było stworzyć klasę, wczytać ją i utworzyć instancję w czasie wykonywania.

0

Tak, jest to możliwe.

Możesz tworzyć klasy z Javassist w środowisku wykonawczym, definiując treść klasy i sprawiając, że javassist skompiluje nową klasę.

Javassist ma niestandardowy kompilator, który tworzy kod bajtowy w oparciu o definicję klasy. Ma pewne szczególne sposoby radzenia sobie z rzeczami, ale korzystanie z tej biblioteki jest bardzo łatwe i intuicyjne.

Javassist jest używany na JBoss, i myślę, że jest to dobre odniesienie :)

To samo można osiągnąć z BCEL, jednak jest to znacznie trudniejsze (ale w ten sposób masz większą kontrolę nad tym, co jest generowany).

0

Prawdopodobnie możesz zrobić coś takiego z JRuby, lub JPython lub Groovy, jeśli musisz.

Jeśli czujesz się wyjątkowo masochistycznie, możesz spojrzeć na BCEL.

0

Jeśli chcesz Java i metaprogramowanie, użyj Groovy.

+0

Cześć Stefan, więc Groovy może pomóc skompilować w środowisku wykonawczym klasę Java w locie i utworzyć jej instancję? Czy masz jakiś wskaźnik o tym, jak to zrobić? – Sergio

0

ASM jest biblioteką kodu bajtowego najniższego poziomu dla Java, tak przypuszczam. To sprawia, że ​​jest bardzo trudny, ale także bardzo silny.Polecam lekturę dokumentacji ASM (PDF), aby naprawdę zrozumieć, jak działa generowanie kodu bajtowego w Javie. Ta dokumentacja wyjaśnia również, jak załadować kod bajtowy w programie ładującym klasy (inny trudny temat, aby zrobić dobrze).

Po tym można użyć jednej z bibliotek wyższego poziomu, jeśli ułatwia to życie i zrozumieć, co robią. W wielu przypadkach, takich jak generowanie serwerów proxy, funkcja CGLIB jest przydatna i prosta w użyciu. Aby uzyskać więcej mocy, wielu wspomniało o Javassist (nie używałem tego - CGLIB i ASM były dla mnie dobre).

1

Może Najprostszym rozwiązanie (w zakresie nie wymaga dodatkowych bibliotek) byłoby użyć Java compiler API że pochodzi z Java 6. Wystarczy po prostu być w stanie wygenerować .java, kompilacji, a następnie wykonać Class.forName().

+0

, który działałby tylko, gdyby pakiet jdk był zainstalowany, prawda? – Sergio

0

Pojawiło się ostatnio pytanie dotyczące in-memory compilation, które powinno zawierać wskazówki, co należy zrobić po wygenerowaniu kodu źródłowego.

Powiązane problemy