Pergunta

Estou tentando codificar um aplicativo que executa plataformas Java diferentes da ONU como J2SE, J2ME, Android etc. Já sei que vou ter que reescrever a maior parte da interface do usuário para cada plataforma, mas quero reutilizar a lógica principal.

Manter este núcleo portátil envolve três desvantagens que eu conheço:

  1. Manter para o velho Java 1.4 Sintaxe, não usando nenhum dos recursos de idioma legal do Java 5.0
  2. apenas usando Bibliotecas externas que são conhecidos por funcionar nessas plataformas (ou seja: não use o JNI e não tenha dependências para outras libs que violam essas regras)
  3. Somente usando o classes que estão presentes Em todas essas plataformas

Eu conheço maneiras de superar (1): codificar no estilo 5.0 e convertê -lo automaticamente em 1.4 (Retroweaver - ainda não tentei, mas parece bom).

Eu penso (2) é um problema que eu só tenho que aceitar.

Agora eu gostaria de saber qual é o melhor trabalho para (3), especialmente aulas de coleção, que mais sinto falta. Eu posso pensar nesses:

  • A maioria dos programadores que eu conheço simplesmente não usa Set, Map, List, etc. e fallback para Vector e matrizes simples. Eu acho que isso deixa o código feio em primeiro lugar. Mas também sei que a escolha certa entre TreeSet/Hashset ou LinkedList/ArrayList é crucial para o desempenho e sempre usando Vector E as matrizes não podem estar certas.
  • Eu poderia codificar minhas próprias implementações dessas classes. Isso parece estar reinventando a roda, e acho que não poderia fazê -lo tão bom quanto os outros fizeram.
  • Como o Java é de código aberto, eu poderia pegar o código SourceCode da estrutura de coleções J2SE e incluir no meu aplicativo ao criar o J2ME. Não sei se isso é uma boa ideia, no entanto. Talvez haja boas razões para não fazer isso.
  • Talvez já existam bibliotecas por aí, que reconstruem os recursos mais importantes da estrutura de coleções, mas são otimizados para sistemas de baixa qualidade, talvez por não implementar a funcionalidade usada com pouca frequência. Você conhece algum?

Obrigado por suas respostas e opiniões!

Editar: Finalmente encontrei uma solução (complexa, mas agradável) e pensei em fornecer minha própria resposta e aceitá -la, a solução se tornaria visível no topo. Mas, pelo contrário, minha resposta ainda está no fundo.

Foi útil?

Solução 2

Já faz um tempo desde que fiz essa pergunta, e desde que encontrei uma solução agradável e funcionando para o problema, mas desde então eu tinha esquecido a você.

Meu foco principal foi a estrutura de coleções Java, que faz parte do java.util pacote.

Finalmente, peguei o código -fonte do Suns Java 6.0 e copiei todas as classes que pertencem à estrutura de coleções em um projeto próprio. Este era um projeto Java 6.0, mas usei os frascos do J2ME como ClassPath. A maioria das classes que copiei depende de outras classes J2SE, para que haja dependências quebradas. De qualquer forma, foi muito fácil cortar essas dependências, deixando de fora tudo o que lida com a serialização (o que não é uma prioridade para mim) e alguns pequenos ajustes.

Compilei a coisa toda com um compilador Java 6, e o retrotranslator foi usado para portar o bytecode resultante de volta ao Java 1.2.

O próximo problema é o nome do pacote, porque você não pode entregar aulas de java.util Com um aplicativo J2ME e carregá -los - o carregador de classe Bootstrap não analisa o arquivo JAR de aplicativos, os outros carregadores de inicialização não podem carregar algo com esse nome de pacote e, no J2ME, você não pode definir carregadores de classe personalizados. O retrotranslator não apenas converte Bytecode, mas também ajuda a alterar as referências de nome no bytecode existente. Eu tive que me mudar e renomear todas as classes em meu projeto, por exemplo java.util.TreeMap passou a ser my.company.backport.java.util.TreeMap_.

Consegui escrever um aplicativo J2ME real em um segundo projeto Java 6.0 que referenciou o usual java.util.TreeMap, usando a sintaxe genérica para criar coleções de tipo seguras, compilar esse aplicativo para o código Java 6.0 Byte e executá-lo através do retrotranslator para criar código Java 1.2 que agora referencia my.company.backport.java.util.TreeMap_. Observe que TreeMap é apenas um exemplo, ele realmente funciona para toda a estrutura de coleções e até para frascos J2SE de terceiros que fazem referência a essa estrutura.

O aplicativo resultante pode ser embalado como um arquivo JAR e JAD e funciona bem nos emuladores J2ME e nos dispositivos reais (testados em um Sony Ericsson W880i).

Todo o processo parece bastante complexo, mas como eu usei a ANT para a automação de construção, e eu precisava de retranslator de qualquer maneira, houve apenas uma sobrecarga única para configurar a estrutura de coleção Backport.

Como afirmado acima, eu fiz isso há quase um ano e escrevi isso principalmente do topo da minha cabeça, então espero que não haja erros. Se você estiver interessado em mais detalhes, deixe -me um comentário. Eu tenho algumas páginas de documentação alemã sobre esse processo, que eu poderia fornecer se houver alguma demanda.

Outras dicas

O J2ME é brutal, e você só terá que se resignar a fazer sem algumas das sutilezas de outras plataformas. Acostume -se a hashtable e vetor, e escrevendo seus próprios invólucros em cima deles. Além disso, não cometa o erro de assumir que o J2ME também é padrão, pois a JVM de cada fabricante pode fazer as coisas de maneiras profundamente diferentes. Eu não me preocuparia muito com o desempenho inicialmente, pois apenas obter correção no J2ME é um desafio suficiente. É possível escrever um aplicativo que atravessa J2ME, J2SE e Android, como eu fiz, mas é preciso muito trabalho. Uma sugestão que eu teria é que você escreva o núcleo da lógica do seu aplicativo e o mantenha estritamente com java.lang, java.util e java.io. Em qualquer lugar onde você esteja fazendo algo que possa interagir com a plataforma, como o sistema de arquivos ou a rede, você pode criar uma interface com a qual o código do aplicativo principal interage, com o qual você possui implementações diferentes para os diferentes ambientes. Por exemplo, você pode ter uma interface que encerra coisas HTTP e usa javax.microedition.io.httpConnection com j2me e java.net.httpurlConnection no Android. É uma dor, mas se você deseja manter um aplicativo em execução nos três ambientes, ele pode levá -lo até lá. Boa sorte.

Enfrentamos exatamente esta situação no desenvolvimento zxing. Se o J2ME estiver na sua lista de metas, esse é o seu fator limitante de longe. Tivemos o MIDP 2.0 / CLDC 1.1. Se você tiver um requisito semelhante, precisará seguir o Java 1.2. Os recursos do idioma Java 1.4 definitivamente não estão presentes (como assert) e, em geral, você não encontrará nada depois de 1.2 no J2me.

Não usamos bibliotecas externas, mas você pode empacotá -las no seu arquivo .jar implantado com poucos problemas. Isso tornaria o .Jar resultante maior, e isso poderia ser um problema. (Então você pode experimentar otimizadores/encolhimento como o ProGuard para mitigar isso.)

Acabei reimplementando algo como coleções.sort () e comparador, pois precisávamos delas e elas não estão no J2ME. Então, sim, você pode considerar fazer isso nos casos, embora apenas quando necessário.

Usamos vetor e hashtable e matrizes, pois não há outra escolha, na verdade, no J2ME. Eu os usaria, a menos que você tenha um motivo para não, e isso seria um desempenho, eu acho. Em teoria, os fabricantes de JVM já estão otimizando sua implementação, mas isso não significa que você não poderia fazer um melhor ... acho que ficaria surpreso se valesse a pena na grande maioria dos casos. Apenas certifique -se de realmente precisar fazer isso antes de fazer o esforço.

Para responder parte da sua pergunta, outra biblioteca de coleções seria Javolução que pode ser construído para J2me.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top