Как справиться с наиболее распространенными классами, отсутствующими в J2ME

Я пытаюсь кодировать приложение, которое запускает разные Java-платформы, такие как J2SE, J2ME, Android и т. Д. Я уже знаю, что мне придется переписать большую часть пользовательского интерфейса для каждой платформы, но я хочу повторно использовать основную логику.

Сохранение портативности этого ядра связано с тремя известными мне недостатками:

  1. Сохранение старого синтаксиса Java 1.4, без использования каких-либо хороших языковых функций Java 5.0.
  2. только с использованием внешних библиотек, которые, как известно, работают на этих платформах (то есть: не используйте JNI и не имеете зависимостей от других библиотек, которые нарушают эти правила)
  3. только с использованием классов, которые присутствуют на всех этих платформах

Я знаю способы преодолеть (1): код в стиле 5.0 и автоматически преобразовать его в 1.4 (retroweaver - еще не пробовал, но вроде нормально).

Я думаю, что (2) - это проблема, с которой мне просто нужно смириться.

Теперь я хотел бы знать, что лучше всего подходит для (3), особенно для классов коллекций, которых я скучаю больше всего. Я могу думать о них:

  • Большинство знакомых мне программистов просто не используют Set, Map, List и т. Д. И прибегают к Vector и обычным массивам. Я думаю, что это в первую очередь делает код уродливым. Но я также знаю, что правильный выбор между TreeSet/Hashset или LinkedList/ArrayList имеет решающее значение для производительности, и постоянное использование Vector и массивов не может быть правильным.
  • Я мог кодировать свои собственные реализации этих классов. Это похоже на изобретение велосипеда, и я думаю, что не смог бы сделать это так хорошо, как другие.
  • Поскольку Java является открытым исходным кодом, я мог взять исходный код платформы J2SE Collections и включить его в свое приложение при сборке для J2ME. Но я не знаю, хорошая ли это идея. Возможно, есть веские причины не делать этого.
  • Возможно, уже существуют библиотеки, которые перестраивают наиболее важные функции структуры коллекций, но оптимизированы для систем низкого уровня, возможно, за счет того, что не реализуют функциональность, которая используется нечасто. Вы знаете кого-нибудь?

Спасибо за ответы и мнения!

Изменить: я наконец нашел (сложное, но приятное) решение, и я подумал, что, предоставив свой собственный ответ и приняв его, решение станет видимым вверху. Но мой ответ, напротив, все еще в самом низу.


person Lena Schimmel    schedule 13.05.2009    source источник


Ответы (4)


J2ME жесток, и вам просто придется смириться с тем, чтобы обходиться без некоторых тонкостей других платформ. Привыкайте к Hashtable и Vector, а также напишите свои собственные оболочки поверх них. Кроме того, не делайте ошибки, предполагая, что J2ME является стандартным, поскольку JVM каждого производителя может делать вещи совершенно разными способами. Поначалу я бы не стал сильно беспокоиться о производительности, так как просто получить корректность на J2ME - достаточно сложно. Можно написать приложение, работающее на J2ME, J2SE и Android, как я это сделал, но это требует большой работы. Одно из моих предложений - написать ядро ​​логики приложения и строго придерживаться java.lang, java.util и java.io. Везде, где вы собираетесь делать что-то, что может взаимодействовать с платформой, например файловая система или сеть, вы можете создать интерфейс, с которым взаимодействует ваш основной код приложения, и у вас есть разные реализации для разных сред. Например, у вас может быть интерфейс, который обертывает HTTP-файлы и использует javax.microedition.io.HttpConnection с J2ME и java.net.HttpURLConnection на Android. Это больно, но если вы хотите, чтобы приложение работало во всех трех средах, это поможет вам. Удачи.

person jjb    schedule 15.05.2009

Прошло некоторое время с тех пор, как я задавал этот вопрос, и я с тех пор нашел хорошее, рабочее решение проблемы, но с тех пор я забыл вам сказать.

Мое основное внимание уделялось Java Collections Framework, который является частью пакета java.util.

Я наконец взял исходный код Suns Java 6.0 и скопировал все классы, принадлежащие фреймворку Collections, в свой собственный проект. Это был проект Java 6.0, но я использовал jar-файлы из J2ME в качестве пути к классам. Большинство из этих классов, которые я скопировал, зависят от других классов J2SE, поэтому зависимости нарушены. В любом случае, было довольно легко избавиться от этих зависимостей, исключив все, что связано с сериализацией (что для меня не является приоритетом) и некоторые незначительные корректировки.

Я скомпилировал все это с помощью компилятора Java 6, и ретротранслятор использовался для переноса полученного байт-кода обратно в Java 1.2.

Следующая проблема - это имя пакета, потому что вы не можете доставить классы из java.util с помощью приложения J2ME и загрузить их - загрузчик классов начальной загрузки не будет смотреть в файл jar приложения, другим загрузчикам не разрешено загружать что-либо с этим имя пакета, а в J2ME вы не можете определять собственные загрузчики классов. Ретротранслятор не только конвертирует байт-код, но также помогает изменять ссылки на имена в существующем байт-коде. Мне пришлось переместить и переименовать все классы в моем проекте, например. java.util.TreeMap стал my.company.backport.java.util.TreeMap_.

Затем я смог написать реальное приложение J2ME во втором проекте Java 6.0, который ссылался на обычный java.util.TreeMap, используя общий синтаксис для создания типобезопасных коллекций, скомпилировать это приложение в байтовый код Java 6.0 и запустить его через ретротранслятор для создания Java 1.2. код, который теперь ссылается на my.company.backport.java.util.TreeMap_. Обратите внимание, что TreeMap - это просто пример, он фактически работает для всей структуры коллекций и даже для сторонних J2SE Jar, которые ссылаются на эту структуру.

Полученное приложение может быть упаковано в файлы jar и jad и отлично работает как на эмуляторах J2ME, так и на реальных устройствах (проверено на Sony Ericsson W880i).

Весь процесс кажется довольно сложным, но поскольку я использовал Ant для автоматизации сборки, а ретранслятор мне все равно понадобился, на настройку бэкпорта фреймворка коллекции были только одноразовые накладные расходы.

Как указано выше, я сделал это почти год назад и писал это в основном с головы до ног, поэтому я надеюсь, что в нем нет ошибок. Если вас интересуют подробности, оставьте мне комментарий. У меня есть несколько страниц документации по этому процессу на немецком языке, которые я могу предоставить, если будет необходимость.

person Lena Schimmel    schedule 04.07.2010
comment
Не могли бы вы предоставить свой бэкпорт фреймворка коллекций? Ретротранслятор великолепен, но мне пришлось написать свои собственные бэкпорты, чтобы заставить работать автобокс. - person Ralf; 06.11.2010
comment
Есть ли шанс, что вы могли бы поделиться этим бэкпортом? - person domino; 13.07.2011

Мы столкнулись именно с этой ситуацией при разработке zxing. Если J2ME находится в вашем списке целей, это, безусловно, ваш ограничивающий фактор. Мы нацелены на MIDP 2.0 / CLDC 1.1. Если у вас есть подобное требование, вам нужно придерживаться Java 1.2. Возможности языка Java 1.4 определенно отсутствуют (например, assert), и в целом вы не найдете ничего после 1.2 в J2ME.

Мы не использовали внешние библиотеки, но вы могли легко упаковать их в развернутый файл .jar. Это сделало бы получившийся .jar больше, и это могло быть проблемой. (Затем вы можете попробовать оптимизаторы / программы сжатия, такие как ProGuard, чтобы смягчить это.)

В итоге я переопределил что-то вроде Collections.sort () и Comparator, поскольку они нам были нужны, а их нет в J2ME. Так что да, вы можете подумать о том, чтобы сделать это в некоторых случаях, но только там, где это необходимо.

Мы использовали Vector, Hashtable и массивы, так как в J2ME другого выбора, на самом деле, нет. Я бы просто использовал их, если у вас нет причин не делать этого, и я думаю, это будет производительность. Теоретически производители JVM уже оптимизируют свою реализацию, но это не значит, что вы не можете сделать что-то лучше ... Думаю, я был бы удивлен, если это того стоит в подавляющем большинстве случаев. Просто убедитесь, что вам действительно нужно это сделать, прежде чем прилагать усилия.

person Sean Owen    schedule 15.05.2009
comment
Исправление о Java ME: CLDC использует код версии 1.3, CDC использует 1.4. Я не могу сейчас вспомнить, какие были изменения между 1.2 и 1.3, но CLDC использует 1.3. - person Malcolm; 20.06.2009
comment
Не было изменений языка с 1.2 до 1.3, только изменения API и JVM. Конечно, у CLDC есть совершенно другое подмножество API и JVM. Так что я полагаю, что оба варианта правильны, но я полагаю, что ваше заявление правильнее, учитывая указанные даты. - person Sean Owen; 12.03.2012
comment
Вау, не думал, что на такой старый комментарий можно ответить. Мое замечание фактически поддерживается спецификацией CLDC, в которой говорится, что CLDC поддерживает ряд классов, унаследованных от Java Standard Edition версии 1.3.1. Я согласен, однако, что язык не изменился между версиями Java 1.2 и 1.3 (второй JLS применяется к обеим), и поскольку CLDC является очень ограниченным подмножеством, ужасной разницы нет. - person Malcolm; 12.03.2012

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

person BenM    schedule 14.05.2009
comment
Привет, спасибо, выглядит интересно. Знаете ли вы, нужно ли мне использовать весь материал Javolution (что, безусловно, приятно, но может иметь другие проблемы / недостатки), если я могу использовать коллекцию из Javolution самостоятельно? - person Lena Schimmel; 14.05.2009
comment
Я не уверен, я никогда не использовал его таким образом, поэтому не могу вам сказать. - person BenM; 15.05.2009
comment
Я тоже задавался вопросом об этом, но, судя по моему опыту попыток изолировать всего несколько классов коллекций, внутри самой библиотеки есть много взаимозависимостей. - person Marc Novakowski; 19.05.2009