динамическая загрузка Dex файла в Dalvik
Dec. 15th, 2010 02:49 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
В общем и с явовской виртуальной машиной вышло по сценарию -- "хотели как лучше, а получилось -- как всегда." ;-) Вроде бы делали универсальный байткод, который write once, run anywhere... Сделали. Но теперь неймется компании Google, которая мало того, что написала для Явы новую виртуальную машину, да еще к тому-же и совершенно другой архитектуры.
Большинству, конечно, все равно, они свои программы перекомпилируют специальным гуглевским компилятором (который из обычных Java class files делает Dalvik-овские dex файлы). А что делать нам, несчастным писателям компиляторов ? ;-)
Но мало того, то байткод другой архитектуры. Еще и загружать динамически его приходится по-новому. И не просто по-новому, оказывается сам этот байткод Dalvik загрузить непосредственно не может, только из zip архива... В общем, грабли на граблях.
Ну вот я вроде разобрался. Пишу, чтобы зафиксировать. Вам это, скорее всего, будет не интересно. ;-)
Итак, возьмем программу Hello.java с одним единственным методом hello, который очевидно что делает. Задача в том, чтобы загрузить этот файл в Андроид динамически, непосредственно в двоичном виде.
Тоесть загрузить нужно Вот этот zip файл, созданный командой:
Ну не жуть ли ? ;-)
Так что, наступает эра многоплатформенных компиляторов в явовские байткоды со всеми вытекающими "прелестями". Да, явовский байткод не очень оптимален в плане используемого пространства, но неужели такая оптимизация, всего-лишь в несколько раз, стоила того ? И все равно-ж, гады, в процессе загрузки этого .zip с файлом .dex (вызов конструктора DexFile), они докомпилируют его в "оптимизированный" байткод в формате .odex, который еще хранят в отдельном файле.
Вот такая вот бессмысленная политика (ибо по-другому мне это сложно объяснить). Нет, для меня это, конечно, выгодно. Я то думал проект уже закончен. А тут опа, появляется возможность переписать все заново (с сохранением старого, проверенного и удобного API). Типа раз, и снова в девках. ;-) Хорошо, но бессмысленно.
По-хорошему нужно было спрятать свой dalvik подальше (как implementation detail, раз уж они верят, что именно такой подход даст им performance edge), включить в стандартную поставку перекомпилятор dx в прозрачном режиме и пройти явовский testsuite.
Большинству, конечно, все равно, они свои программы перекомпилируют специальным гуглевским компилятором (который из обычных Java class files делает Dalvik-овские dex файлы). А что делать нам, несчастным писателям компиляторов ? ;-)
Но мало того, то байткод другой архитектуры. Еще и загружать динамически его приходится по-новому. И не просто по-новому, оказывается сам этот байткод Dalvik загрузить непосредственно не может, только из zip архива... В общем, грабли на граблях.
Ну вот я вроде разобрался. Пишу, чтобы зафиксировать. Вам это, скорее всего, будет не интересно. ;-)
Итак, возьмем программу Hello.java с одним единственным методом hello, который очевидно что делает. Задача в том, чтобы загрузить этот файл в Андроид динамически, непосредственно в двоичном виде.
Тоесть загрузить нужно Вот этот zip файл, созданный командой:
javac Hello.java && \ dx --dex --output=Hello.zip Hello.class && \ adb -e push Hello.zip /data/localЧтобы это сделать, нужна вот такая программа SayHello.java, которая компилируется и работает вот так:
javac SayHello.java && \ dx --dex --output=SayHello.zip SayHello.class && \ adb -e push SayHello.zip /data/local \ adb -e shell dalvikvm -classpath /data/local/SayHello.zip SayHello Note: SayHello.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 43 KB/s (2034 bytes in 0.045s) Hi ! Im' your "Hello World" loader ! First, I'm hooking the DexFile class...Good. Second, I'm getting hold of its constructor...Good. Third, I'm instantiating the DexFile object on "/data/local/Hello.zip"...Good. Fourth, I'm getting to its loadClass method...Good. Fifth, loading Hello class from the loaded dex...Good. Sixth, getting hello method of Hello class...Good. Seventh, invoking the hello method: Hello WORLD ! Done. Easy, isn't it ? ;-)
Ну не жуть ли ? ;-)
Так что, наступает эра многоплатформенных компиляторов в явовские байткоды со всеми вытекающими "прелестями". Да, явовский байткод не очень оптимален в плане используемого пространства, но неужели такая оптимизация, всего-лишь в несколько раз, стоила того ? И все равно-ж, гады, в процессе загрузки этого .zip с файлом .dex (вызов конструктора DexFile), они докомпилируют его в "оптимизированный" байткод в формате .odex, который еще хранят в отдельном файле.
Вот такая вот бессмысленная политика (ибо по-другому мне это сложно объяснить). Нет, для меня это, конечно, выгодно. Я то думал проект уже закончен. А тут опа, появляется возможность переписать все заново (с сохранением старого, проверенного и удобного API). Типа раз, и снова в девках. ;-) Хорошо, но бессмысленно.
По-хорошему нужно было спрятать свой dalvik подальше (как implementation detail, раз уж они верят, что именно такой подход даст им performance edge), включить в стандартную поставку перекомпилятор dx в прозрачном режиме и пройти явовский testsuite.
no subject
Date: 2010-12-15 02:26 am (UTC)no subject
Date: 2010-12-15 03:23 pm (UTC)Сейчас я пытаюсь понять -- нужно для него писать Dalvik backend или нет... Для приложений в Андроид такой мини-компилятор очень бы пригодился. Но переписывать кодогенератор -- занятие не из легких... Тем более, под другую архитектуру... Хотя, все возможно, принципиальных проблем нет, стек в регистрах запросто эмулируется.
К.Л.М.
no subject
Date: 2010-12-15 04:30 pm (UTC)Например, в Open Galaxy Viewer (http://sourceforge.net/projects/ogv/) выражения используются для вычисления пользовательских столбцов, фильтров и т.п. Я замерил время -- и все столбцы сделал динамически вычисляемыми (толко оптимизировал специальный случай для простейших выражений вида tech.drive). Прекомпилированные выражения JavaScript вычислялись где-то вдвое медленнее нативных жавовских, а оптимизированные вообще не отличались (в пределах погрешности). util.Evaluator -- сам вычислитель, gui.dialogs.EditColumn -- форма редактирования, с
блекджеком и шлюхамипримитивной подсветкой синтаксиса и деревом свойств.no subject
Date: 2010-12-15 04:53 pm (UTC)JEL -- это один self-contained .jar файл, на 35k.
Так что может, в каких-то случаях и уменьшилась, но все равно использование javax ведет к привязке к конкретной Java платформе и установленным extensions. В случае использования JEL, достаточно просто забросить .jar в проект и всё.
По производительности (во время выполнения и во время компиляции) вряд-ли будет быстрее JEL. Во-первых, поскольку нормальная JVM очень круто оптимизирует (движкам скриптовых языков до этого еще расти), а во-вторых интерфейс с приложением прямой, без всяких посредников. Компиляция однопроходная.
К.Л.М.
no subject
Date: 2010-12-15 05:17 pm (UTC)Так что область востребованности JEL сильно сузилась. Хм-м-м, может попробовать использовать в OGV? Текущие потребности удовлетворяет, +5% размера допустимо. Нет, универсальность и расширяемость, пожалуй, важнее.
no subject
Date: 2010-12-15 05:37 pm (UTC)Но не нужно забывать, что проекту уже 12 лет.
Тем не менее, эта библиотека очень даже востребована и актуальна по сей день. В первую очередь, за счет малого размера, простоты и более универсальной доступности на различных Java платформах. Причем, не обязательно использовать язык JEL, я знаю народ, который выбрасывает парсер и цепляет JEL в качестве кодогенератора.
К.Л.М.
no subject
Date: 2010-12-15 06:40 pm (UTC)Как минимум, сделать компилятор в Далвик -- интересная задача. А значит, стоящая. Я делал компиляторы и для менее осмысленных вещей.
no subject
Date: 2010-12-15 08:17 pm (UTC)Вот Вы знаете, что они там себе в Гугле думают ? Я лично твердого ответа по поводу их дальнейших планов насчет dalvik не нашел... Они таки собираются делать fork байткода, или таки сделают свою библиотеку (в т.ч. и класс ClassLoader) полностью совместимой с явовской ?
К.Л.М.