ht=34 alt=imagem_pdf.jpg src="/imagens/imagem_pdf.jpg" width=34 border=0>
Edições do Java e JavaScript
Estou querendo aprender a programar em Java e ficar bem informado sobre o assunto assinando a revista Java Magazine, mas antes gostaria de tirar algumas dúvidas. Qual a diferença entre J2ME, J2SE, J2EE e JavaScript?
Bruno S.R.
J2ME, J2SE e J2EE (que recentemente perderam o "2", passando a ter as abreviações JME, JSE e JEE) são edições da plataforma Java. Uma edição especifica recursos fundamentais e APIs disponíveis para um determinado ambiente de execução.
O Java Micro Edition (Java ME ou JME) volta-se a dispositivos com pouca memória e poder de processamento reduzido, em geral alimentados por bateria, como PDAs e celulares, além de outros tipos de hardware embarcados, como sensores e robôs industriais. O Java Standard Edition (Java SE ou JSE) é utilizado em desktops e servidores, para executar aplicações Java ou desenvolver estas aplicações. Muitos recursos disponíveis no JSE não estão disponíveis no JME, porque não seriam comportados em computadores mais simples do que um PC. A Java SE tem a condição especial de ser o coração da tecnologia Java; dele dependem, pelo menos em parte, as outras plataformas. O Java Enterprise Edition (Java EE ou JEE) é voltado a ambientes corporativos de rede, como servidores web e clusters. O JEE acrescenta ao Java SE vários recursos específicos para aplicações que rodam em servidores em vez de na máquina do usuário final.
Finalmente, o JavaScript não tem relação significativa com Java. O nome dessa linguagem, que foi criada pela Netscape, era originalmente "Livescript" sendo modificado para JavaScript quando o navegador web da empresa passou a suportar applets Java. Considera-se que o novo nome foi uma jogada de marketing, pegando carona na fama de Java, e não uma mudança tecnológica. Avaliando-se superficialmente, JavaScript tem algumas semelhanças com Java, por exemplo na sintaxe – mas na prática Java e JavaScript são linguagens muito diferentes.
Grandes volumes em memória
Tenho acompanhado os artigos de Osvaldo Doederlein sobre performance, threads e collections em Java, e de início gostaria de parabenizá-lo pela excelente qualidade dessas matérias.
Estou iniciando um estudo para migrar para Java um processo feito hoje em PowerBuilder, que demora em média uma hora. Tenho quatro fontes principais de dados para este processo: dados principais, ex. contratos (300 mil registros); dados de prestações (4 milhões de registros) e dados de rendas (400 mil registros).
Hoje o processo em PowerBuilder recupera estes dados por cada contrato em tabela do DB2. A solução imaginada seria gerar arquivos textuais com os dados e armazená-los em objetos Hashtable. Entretanto, para as prestações o código original utiliza vários recursos do PowerBuilder, como filtros e ordenação – e a classe Hashtable não possui esses recursos.
É válida, em Java, essa estratégia de manipular grandes quantidades de dados em memória? Caso positivo, como simular com alta performance as funcionalidades faltantes nas classes de coleções?
Israel Santiago
israel.santiago@mercantil.com.br
Obrigado pela apreciação! Quanto ao seu problema, entendo que a idéia é carregar todos esses registros na memória de um só golpe, o que é bem mais rápido que fazer uma consulta para cada registro e então fazer seu processamento todo em memória.
Sobre a manipulação de grandes volumes de dados, não se preocupe. O Java agüenta com tranqüilidade o processamento de milhões de objetos em memória de uma só vez. Já escrevi aplicações que exigiam heaps de alguns gigabytes para executar tarefas semelhantes à sua, que exigiam ler milhões de registros de uma vez, sem encontrar problemas. Logicamente, com estes grandes volumes de heap, você precisa ter bastante RAM e configurar bem a JVM. Use profilers e opções como -verbose:gc. Assim, quando o uso de memória estiver próximo do limite, será fácil ver quais objetos estão enchendo o heap – e a partir daí a solução do problema pode ser simples.
Há excelentes profilers open source, como o Hyades para Eclipse ou o NetBeans Profiler. E se for usado hardware de 64 bits e SMP, melhor ainda, pois o modelo de memória de 64 bits é mais eficiente para heaps grandes (mesmo quando não se passa dos limites de 32 bits), e o multiprocessamento permite usar recursos de garbage collection paralelo e concorrente.
As classes de coleções, como Hashtable e HashMap (sendo a última mais recomendada) de fato não têm métodos de pesquisa sofisticados como as cláusulas where do SQL, ou filtros do PowerBuilder. Mas isso só é problema se os dados forem organizados em memória de forma muito simples, por exemplo colocando todos os contratos num único Map indexado pela chave-primária.
O ideal seria ter um modelo de estruturas de dados em memória que apóie os tipos de pesquisa que você pretende fazer. Por exemplo, se você faz buscas de contratos tanto por ID quanto por nome, poderia colocar cada contrato em dois Map, um indexado pelo ID, e outro pelo nome. No caso de atributos não-únicos como datas, seria possível utilizar estruturas de dados diferentes ou mais complexas. Por exemplo, usar um Map "raiz" cuja chave é o ano, e colocar os valores em outros Map usando como chave o dia do ano (1-366) e os valores em um List com todos os contratos com data naquele dia. Sendo que buscas mais precisas (por hora, minuto) seriam feitas manualmente nas listas do dia.
Outra opção é usar recursos do Apache Commons Collections (jakarta.apache.org/commons/collections), que facilitará alguns desses cenários mais complexos. Para o mesmo exemplo, seria possível usar um MultiHashMap, que permite associar uma mesma chave a vários valores, mas evita a complexidade e o overhead de coleções aninhadas. Mesmo para indexação por atributos únicos, há opções mais interessantes na Commons Collections, como o MultiKeyMap que permite usar uma única coleção para vários critérios de indexação. Além disso, o pacote de "functors" facilita a implementação de operações de busca mais complexas.
Alternativamente ou em paralelo, você deveria ter uma modelagem dos objetos em memória que elimine a necessidade de fazer muitas dessas buscas nas coleções. Por exemplo, se uma prestação no banco de dados possui uma chave estrangeira apontando para um contrato, então o objeto Java que vai representar a prestação deve ter uma referência para seu contrato. Assim, uma vez tendo uma Prestacao p, a obtenção do contrato associado deve exigir somente um p.getContrato(), sem necessidade de fazer novo lookup em um Map (ou outra estrutura) com todos os contratos. Somente na etapa de carga de dados, quando todos esses objetos estão sendo criados, seria preciso fazer tais lookups para definir os relacionamentos nos objetos de valor (VO), mas isso só deve exigir Maps correspondentes à chave primária. Portanto, uma boa modelagem de classes pode evitar a necessidade de escrever muito código de indexação e busca de dados em coleções complexas.
Osvaldo Doederlein
...