Kompilacja kodu w pamięci java w locie dla Java 5 i Java 6
Jak skompilować kod Javy z dowolnego ciągu znaków (w pamięci) w Javie 5 i Javie 6, załadować go i uruchomić na nim określoną metodę (predefiniowaną)?
Zanim to rozpalisz, przejrzałem istniejące implementacje:
- większość opiera się na Java 6 kompilator API. Ci, którzy tego nie robią, polegają na sztuczkach. Tak, sprawdziłem commons-jci. Albo jestem zbyt gęsty, aby zrozumieć, jak to działa, albo po prostu nie.]}
- nie mogłem znaleźć, jak nakarmić kompilator mojej obecnej klasy ścieżka (która jest dość Ogromna).
- w implementacji, która działała (w Javie 6), nie mogłem znaleźć, jak poprawnie załadować wewnętrzne klasy (lub wewnętrzne anonimowe klasy).
- chciałbym, aby całość była w pamięci, ponieważ działa w wielu środowiskach.
Jestem pewien, że to już zostało rozwiązane, ale nie mogę znaleźć niczego, co wygląda nawet na połowę jakości produkcji w google(z wyjątkiem jci, którego, jak mówiłem wcześniej, nie udało mi się użyć).
Edytuj:
- przejrzałem JavaAssist - potrzebuję wewnętrznych klas, obsługi języka Java 5.0 i kompilacji z całą classpath. Chciałbym również tworzyć nowe klasy w locie. I może się mylić, ale nie mogłem znaleźć, Jak to zrobić z JavaAssit.
- jestem skłonny użyć rozwiązania opartego na systemie plików (wywołanie javac), ale nie wiem, jak rozszyfrować classpath, ani jak później załadować pliki (których nie ma w mojej classpath) specjalnym classploaderem, który może być odzyskany dla wiele inwokacji. Chociaż wiem, jak to zbadać, wolałbym gotowe rozwiązanie.
Edit2: Na razie jestem zadowolony z BeanShell "Oceń". Wygląda na to, że robi wszystko, czego potrzebuję (zdobądź ciąg znaków, oceń go w kontekście 'bieżącej' ścieżki klasowej. Brakuje mu niektórych funkcji Javy 5, ale może używać klas enums (nie definiować) i skompilowanych ' generic '(usuwać), więc powinno wystarczyć na to, co chcę.
nie chcę jeszcze oznaczyć odpowiedzi jako zaakceptowanej, ponieważ mam nadzieję na lepsze rozwiązanie.
Edit3: zaakceptowałem sugestię beanshell - to naprawdę działa cudownie.
6 answers
Jeśli nie jesteś całkowicie związany z kompilacją, rozwiązania takie jak Beanshell, groovy i inne języki skryptowe są łatwo osadzane (w rzeczywistości java ma wbudowaną obsługę podłączania języka skryptowego, więc Twój kod nawet nie wie, w jakim języku skrypt jest napisany)
Beanshell powinien uruchomić dowolny 100% kod java IIRC, i wierzę, że Groovy może uruchomić większość kodu java -- prawdopodobnie wszystkie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 21:08:58
JCI wygląda dobrze. Ten fragment kodu powinien być twoją bazą:
JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");
MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());
MemoryResourceStore mrs = new MemoryResourceStore();
CompilationResult result = compiler.compile(sources, mrr, mrs);
// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir
Jakiś powód, dla którego to nie powinno działać?
Edit: Dodano
MemoryResourceStore
, Aby wysłać skompilowane wyjście klasy do pamięci, tak jak wymagano.
Również ustawienie javac
ustawień, takich jak classpath w Twoim przypadku, można wykonać poprzez setCustomArguments(String[] pCustomArguments)
w klasie JavacJavaCompilerSettings
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 21:34:10
Możesz też sprawdzić Janino.
Z ich strony:
Janino jest kompilatorem, który odczytuje wyrażenie JavaTM, blok, ciało klasy, plik źródłowy lub zestaw plików źródłowych i generuje kod bajtowy JavaTM, który jest ładowany i wykonywany bezpośrednio. Janino nie ma być narzędziem programistycznym, ale wbudowanym kompilatorem do celów kompilacji w czasie wykonywania, np. JSP.
Obecnie używam go w dość dużym projekcie o krytycznym znaczeniu i działa dobrze
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 21:32:06
Javassist może Cię zainteresować
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 20:49:50
Uruchom wewnątrz kontenera internetowego, takiego jak Tomcat, i najpierw Wygeneruj stronę JSP, a następnie ją wywołaj.
Pozwala to również pozbyć się starych definicji klas przez zwykłe nadpisanie strony JSP zamiast powolnego uruchamiania programu classloader.
Czy wymóg "in-memory" wynika z szybkości czy z braku zmiany bazy kodu?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 21:39:35
Eclipse dostarcza i używa własnego kompilatora, który nie jest javac
- kompilator Eclipse jest używany wewnątrz IDE (Eclipse)
- kompilator Eclipse może być również używany jako czysty kompilator wsadowy poza zaćmieniem
Skompiluj plik źródłowy
$ java -jar ecj-3.5.2.jar HelloWorld.java
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 18:04:51