dr_klm: (Default)
[personal profile] dr_klm
В общем и с явовской виртуальной машиной вышло по сценарию -- "хотели как лучше, а получилось -- как всегда." ;-) Вроде бы делали универсальный байткод, который write once, run anywhere... Сделали. Но теперь неймется компании Google, которая мало того, что написала для Явы новую виртуальную машину, да еще к тому-же и совершенно другой архитектуры.

Большинству, конечно, все равно, они свои программы перекомпилируют специальным гуглевским компилятором (который из обычных 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.

Date: 2010-12-15 03:12 pm (UTC)
From: [identity profile] dr-klm.livejournal.com
почему бы не сделать просто new dalvik.system.DexFile("/data/local/Hello.zip").loadClass(...)?
Потому, что явовский исходник компилируется стандартным javac (в платформе Андроид нет компилятора Java, только перекомпилятор dex из *.class в один файл .zip, содержащий один файл .dex и MANIFEST), а javac о классе dalvik.system.DexFile ничего не знает. Этот класс существует только внутри Dalvik VM (у него даже нет явовского исходника, насколько я помню).

Спор между регистровыми и стековыми машинами вечен, что доказывает отсутствие подавляющего превосходства одних над другими. И там и там есть свои плюсы и минусы, какие-то операции лучше ложатся на стек, какие-то на регистры. Но это если речь идет о машинах в железе. Для виртуальных машин, которые потом все равно компилируют код на лету, разницы между стековыми и регистровыми архитектурами еще меньше.

К.Л.М.

Date: 2010-12-15 04:10 pm (UTC)
ext_605364: geg MOPO4 (Default)
From: [identity profile] gegmopo4.livejournal.com
Некоторые жавовские стандартные классы тоже не на жаве написаны (Math, например). Но публичный интерфейс есть. Почему бы не быть и dalviklib.jar, содержащему интерфейс к dalvik.system.DexFile? Или же, если это ненужные детали реализации, рекомендованным должно быть простое использование ClassLoader. Не верится мне, что нет прямее пути.

Стековая виртуальная машина просто намного проще, её соберёт и школьник. Все учебные компиляторы компилируют именно в стековую машину, а из регистров используют разве что PC, SP и PSW. На практике же выполнение на дешёвом процессоре с РОН оказывается быстрее (да, жаль, что Форт не занял место Бейсика 30 лет назад, многое бы пошло не так). Ну а сейчас регистровые команды просто легче параллелятся. Так что стек остался в учебниках.

Date: 2010-12-15 04:35 pm (UTC)
From: [identity profile] dr-klm.livejournal.com
Почему бы не быть и dalviklib.jar, содержащему интерфейс к dalvik.system.DexFile?
Почему бы и не быть... Но нету. ;-))

Но краткость записи тут не главное. Хотя да, я подал так, что это бросается в глаза и кажется главным, на первый взгляд... Главное, что я не могу просто загрузить байткод из памяти. Мне его нужно будет: 1) сгенерировать; 2) зазиповать; 3) записать на диск; 4) запустить приведенную выше программу (ну или Ваш, краткий ее аналог), которая заставит Dalvik VM: 4a) раззиповать архив; 4b) "оптимизировать" хранящийся там dex; 4c) записать оптимизированный его вариант .odex на диск; 4d) отобразить (mmap) этот, записанный на диск odex, в память; и только потом, собственно, приступить к инициализации этого класса...

Краткость записи тут не главное. Очень много лишних ненужных действий...

Стековая виртуальная машина просто намного проще, её соберёт и школьник.
Ну, это смотря какой школьник. ;-) Меня, например, в школе больше интересовали игры с нулевым исходом и эффективная реализация алгоритма мини-макс. ;-)) Хотя, согласен, ничего принципиально сложного в стековых машинах нет. Как нет ничего принципиально сложного и в регистровых машинах или в эмуляции стека в регистрах. Да, распределение регистров -- это лишний проход по дереву, но и в этом ничего принципиально сложного нет. Для всего этого есть классические алгоритмы в учебниках.

Тем не менее, между "алгоритмом в учебнике" и "реальным программным продуктом" есть большая разница.

К.Л.М.

Date: 2010-12-15 04:59 pm (UTC)
ext_605364: geg MOPO4 (Default)
From: [identity profile] gegmopo4.livejournal.com
Ага! То есть проблема на самом деле в другом -- что программа на Андроиде должна скомпилировать данное выражение в эффективный код (код Далвика) и (многократно) выполнить его. Вы решаете её методом математика: погасить огонь, вылить огонь из чайника... Может есть краткий путь? Например, какой интерфейс реализует DexFile, может есть другие имплементации?

Date: 2010-12-15 05:23 pm (UTC)
From: [identity profile] dr-klm.livejournal.com
Это не я решаю. На сегодня другого пути загрузить код в Dalvik нет. Только через такое вот многократное выливание воды из чайника. В этом-то, собственно, и проблема...

Причем, я подозреваю, что проблема эта архитектурная. Одна из основных фишек Dalvik в том, что байт код не загружается, а отображается (причем, в формате odex) в память через mmap. Было бы просто, если бы была возможность подсунуть виртуальной машине массив с байткодом в формате odex для непосредственной загрузки. Но, этого мне никто сделать не даст, поскольку odex -- небезопасный формат, там многие проверки уже сделаны (собственно, в этом и заключается "оптимизация" dex -> odex). Если же я стартую с dex, то, по крайней мере, один раз вылить воду из чайника, записав соответствующий odex на диск, а потом торжественно отобразив его обратно в память через mmap сделать прийдется (при этом, заметьте, выигрыш от использования mmap за счет этого полностью сходит на нет). Но и этого мне не дают сделать, поскольку текущая реализация Android позволяет загружать файлы только в формате .zip, содержащие manifest и dex. Тоесть воду прийдется наливать и выливать еще раз.

Гениальные программисты работают в корпорации Google ! ;-)

К.Л.М.

Date: 2010-12-15 06:36 pm (UTC)
ext_605364: geg MOPO4 (Default)
From: [identity profile] gegmopo4.livejournal.com
Я не сомневаюсь в креативности гуглевых программистов (как и программистов любой корпорации, и вообще программистов), но остаётся крохотный шанс, что вы не поняли друг друга. Вот если попробовать использовать JEL как есть, компилируя в жавовский байт-код, -- вдруг подхватит? Встроенный браузер выполняет Java-апплеты?

Если же всё настолько печально, может быть PathClassLoader (http://developer.android.com/reference/dalvik/system/PathClassLoader.html#PathClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader)) сократит полшага, вроде он может читать и незазипованные dex.

Date: 2010-12-15 08:11 pm (UTC)
From: [identity profile] dr-klm.livejournal.com
Если честно, я баллансирую пока между "делать"/"не делать". Что-то мне подсказывает, что текущее положение дел временное и они таки включат "dex" (в стандартную библиотеку)... тогда можно будет просто его вызвать и обойтись малой кровью. Переписывать кодогенератор -- дело муторное. В принципе, он у меня может сгенерировать процентов на 90 того, что может сгенерировать стандартный javac. Переписывать его означало бы браться за задачу, за которую в google не взялись, остановившись на перекомпиляции байткода.

PathClassLoader, а так-же DexClassLoader -- это такое западло для "умников", которые вооружившись тем-же ха-ха Гуглем, думают, что они могут теперь легко беседовать на равных на любые темы от кодогенераторов, до адронного коллайдера. Загрузку непосредственно из raw dex ни PathClassLoader, ни DexClassLoader на сегодня не поддерживает. Да, там написано, что поддерживает, я знаю. Но, если на заборе написано Х.., это-же не значит, что там действительно ... ;-))

Нет, ну Вы попробуйте, конечно... ;-)))

К.Л.М.

Profile

dr_klm: (Default)
Dr. K. L. Metlov

March 2017

S M T W T F S
   1234
567891011
1213141516 1718
19202122232425
262728293031 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 29th, 2025 06:24 am
Powered by Dreamwidth Studios