You are on page 1of 53

EMAG | JAVA: PRESENTE E FUTURO

05.
11.
15.
22.
29.
33.
36.
38.
42.
49.
51.

InfoQ Brasil

Onde foi parar o PermGen do Java?


8 funcionalidades pouco conhecidas do Java 8
Anotaes de tipos no Java 8: Ferramentas
e oportunidades
Java 8: Desmistificando Lambdas
Quo funcional o Java 8?
Java 7 - Caractersticas que viabilizam o Java 8
Q&A: Novidades do Java 8
Do Groovy ao Java 8
Nashorn: Combinando o poder do Java
e JavaScript no JDK 8
Java 9 e alm: Brian Goetz e John Rose falam
sobre o futuro do Java
Novos Horizontes do Java

CONTEDO DETALHADO
Onde foi parar o PermGen do Java? . . . . . . . . . . . . . . . . . . . . . 5

Adeus PermGen. Ol Metaspace! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5


Mudana para o Metaspace e suas alocaes . . . . . . . . . . . . . . . . 6
Otimizao e Metaspace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Questes Atuais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

8 funcionalidades pouco conhecidas do Java 8 . . 11









1. StampedLock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2. Adicionadores concorrentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3. Ordenao Paralela . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12
4. Migrando para nova API de data . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5. Controle de processos do sistema operacional . . . . . . . . . . 13
6. Operaes numricas precisas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Gerao segura de nmeros aleatrios . . . . . . . . . . . . . . . . . . . 13
8. Referncias opcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Anotaes de tipos no Java 8: Ferramentas


e oportunidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Sintaxe das anotaes de tipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Detectando erros com anotaes . . . . . . . . . . . . . . . . . . . . . . . . . . . .
O framework Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Aumentando a produtividade com anotaes de tipo . . . .
A estrada frente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Concluso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16
17
18
19
20
21

Java 8: Desmistificando Lambdas . . . . . . . . . . . . . . . . . . . . . . 22


Referncia de mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Evoluo da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Operaes de agregao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fontes de stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Operaes de finalizao de Stream . . . . . . . . . . . . . . . . . . . . . . . . .
Inteface Iterable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Concluso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24
25
25
26
26
26
28

Quo funcional o Java 8? . . . . . . . . . . . . . . . . . . . . . . . . . . 29


O que uma linguagem de programao funcional? . . . . 29

Programao funcional em linguagens no


funcionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Java - um pouco de histria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
O sistema de tipos original do Java . . . . . . . . . . . . . . . . . . . . . . 30
Alternativas a tipos nomeados . . . . . . . . . . . . . . . . . . . . . . . . . . 31
O sistema de tipos do Java 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Recursos introduzidos no Java 6 e 7 . . . . . . . . . . . . . . . . . . . . . 31
O sistema de tipos do Java 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Quo funcional o Java 8? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Java 7: Caractersticas que viabilizam o Java 8 . . . 33


Operador Diamante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Manipulador de Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
invokedynamic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Concluso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

Q&A: Novidades do Java 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . 36


Do Groovy ao Java 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Nashorn: Combinando o poder do Java
e JavaScript no JDK 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Shell scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Passando dados para o Java e vice-versa . . . . . . . . . . . . . . . . 45
Usando classes Java no Nashorn . . . . . . . . . . . . . . . . . . . . . . . . 45
Linguagem funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Dialeto especial do JavaScript no Nashorn . . . . . . . . . . . . . . 46
Avatar.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Resumindo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

Java 9 e alm: Brian Goetz e John Rose falam


sobre o futuro do Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Novos Horizontes do Java . . . . . . . . . . . . . . . . . . . . . . . . . . . 51


Primeiros anncios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Outras novidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Data final quase definida, com alguns sacrifcios . . . . . . . . . 52

APRESENTAO

Java 8 o release atual do Java desde 2014, mas para alguns


ainda um sonho que o legado no deixa se concretizar. Por
outro lado, ambientes empresariais e grupos de desenvolvedores esto se modernizando e gradualmente tornando o novo Java
mainstream. Com o Java 9 planejado para o primeiro semestre de
2017, a verso 8 da linguagem/plataforma mais popular do mundo
a realidade que queremos conhecer e alcanar hoje. Com essa eMag,
buscamos oferecer uma base para voc explorar as muitas novidades
do Java 8 de novas APIs a mudanas na linguagem. Tambm vislumbramos um pouco do futuro, concluindo essa coleo de artigos
do InfoQ com um apanhado do que est por vir no Java 9.
O Java 8 contm novas funcionalidades, aprimoramentos e correes de bugs para maior eficincia no desenvolvimento e na execuo;
traz features voltadas ao aumento de produtividade e facilidade de
uso, alm de melhorias em programao poliglota, segurana e performance. Se as verses 6 e 7 do Java foram alteraes consideradas
leves, o Java 8 est em outro patamar. Mais de 56 novas funcionalidades foram adicionadas. Chegaram os lambdas, mtodos padro,
interfaces funcionais e a API de streams, modificando radicalmente
a linguagem e portanto todo o ecossistema Java. H ainda uma nova
API para datas, novas anotaes e aumento de desempenho do engine para JavaScript.
Neste eMag, o InfoQ leva praticantes numa visita atravs do Java
8 e as futuras verses da linguagem, explorando como chegamos at
aqui e algumas formas que seguiremos adiante com a tecnologia.

InfoQ Brasil

ONDE
FOI
PARAR
O
PERMGEN
DO
JAVA?
por Monica Beckwith, traduzido por Rafael Brito
Com a introduo do JDK8, no existe mais o espao de PermGen. Os metadados que antes eram armazenados no PermGen no desapareceram,
mas foram movidos para a memria nativa, em uma rea conhecida como Metaspace. Conhea neste artigo maiores detalhes desta importante
mudana da plataforma Java.

Mquina Virtual do Java


(JVM) utiliza uma representao interna de suas classes
contendo uma srie de metadados por
classe, tais como: informaes de hierarquia de classes, dados e informaes de mtodos (tais como bytecodes, pilha e tamanho de variveis), o
pool contnuo em tempo de execuo,
resolues de referncias simblicas e
Vtables.
Anteriormente, quando os classloaders customizados no eram to
comuns, as classes eram estticas
em sua maioria, raramente eram descarregadas ou coletadas, e consequentemente eram marcadas como permanentes. Alm disso, desde que as
classes fizessem parte da implementao da JVM, e no fossem criadas

pela aplicao, elas eram consideradas como memria no pertencente


ao heap.
Na JVM HotSpot antecessora ao
JDK8, a representao permanente
ficava em uma rea chamada permanent generation (gerao permanente). A gerao permanente era
contgua ao heap do Java e limitada a
-XX:MaxPermSize, que precisava ser
configurada por linha de comando
antes de iniciar a JVM, caso contrrio seria iniciada com o valor padro
de 64M (85M para 64bit scaled pointers - ponteiros auto-incrementveis
com deslocamentos constantes, que
facilitam o acesso estrutura). A coleo da gerao permanente ficaria
associada coleo da antiga gerao, ento sempre que alguma delas

ficassem cheias, ambas as geraes


(permanentes e antigas) seriam coletadas. Um dos problemas mais bvios
que se pode verificar de imediato a
dependncia do -XX:MaxPermSize. Se
o tamanho das classes de metadados
estiver alm dos limites do -XX:MaxPermSize, sua aplicao ser executada com pouco espao de memria
e um erro de Out of Memory ser
apresentado.
Curiosidade: Antes do JDK7, para
a JVM HotSpot, as Strings internalizadas (interned) tambm eram mantidas na gerao permanente, tambm
conhecida como PermGen, causando muitos problemas e erros de Out
of Memory. Para mais informaes
acesse a documentao desse problema.

eMag | Java: Presente e Futuro

Adeus PermGen.
Ol Metaspace!
Com o surgimento do JDK8, PermGen no existe mais. As informaes
de metadados no desapareceram, s
que o espao em que eram mantidos
no mais contguo ao heap. Agora, o
metadado foi movido para a memria
nativa, em uma rea conhecida como
Metaspace.

Mudana para o Metaspace e


suas alocaes
Agora a VM Metaspace (Mquina
Virtual Metaspace) emprega tcnicas
de gerenciamento de memria para
gerenciar o Metaspace. Movendo assim o trabalho de diferentes coletores
de lixo para uma nica VM Metaspace. Uma questo por trs do Metaspace reside no fato de que o ciclo
de vida das classes e seus metadados
corresponde ao ciclo de vida dos classloaders. Isto , quanto mais tempo o
classloader estiver ativo, mais o metadado permanecer ativo no Metaspace e no poder ser liberado.
Temos usado o termo Metaspace
de forma muito vaga neste texto. Mais

InfoQ Brasil

A mudana para o Metaspace foi


necessria, pois era realmente difcil
de se fazer o ajuste fino (tunning) do
PermGen. Havia ainda a possibilidade dos metadados serem ser movidos
por qualquer coleta de lixo completa.
Alm disso, era difcil dimensionar
o PermGen, uma vez que o seu tamanho dependia de muitos fatores,
tais como: o nmero total de classes,
tamanho dos pools constantes, tama-

nhos dos mtodos etc.


Adicionalmente, cada garbage collector na HotSpot precisava de um cdigo especializado para lidar com os
metadados no PermGen. Desacoplar
os metadados do PermGen no s
permite o gerenciamento contnuo do
Metaspace, como tambm melhorias,
tais como: simplificao da coleta de
lixo completa e futura desalocao
concorrente de metadados de classe.

formalmente, a rea de armazenagem


por classloader chamado de metaspace, e estes metaspaces so coletivamente chamados Metaspace.
A reciclagem ou recuperao de metaspace por classloader pode ocorrer
somente depois que o seu classloader
no estiver mais ativo e foi relatado
como inativo pelo coletor de lixo. No
h realocao ou compactao nestes
metaspaces, mas os metadados so
varridos por referncias Java.
A VM Metaspace gerencia a alocao de Metaspace empregando um
alocador de segmentos. O tamanho
dos segmentos depende do tipo de
classloader. H uma lista global de
segmentos livres. Sempre que um

classloader precisa de um segmento,


remove-o da lista global e mantm a
sua prpria lista de segmentos. Quando algum classloader finalizado,
seus segmentos so liberados e retornam novamente para a lista global de
segmentos livres. Esses segmentos
so posteriormente divididos em blocos e cada bloco contm uma unidade
de metadados. A alocao de blocos
dos segmentos linear (ponteiro de
coliso). Os segmentos so alocados
fora dos espaos de memria mapeada (mmapped). H uma lista ligada
para os tais espaos globais mmapped
virtuais, e sempre que algum espao
virtual esvaziado, ele devolvido ao
sistema operacional.

A figura acima mostra a alocao


de Metaspace com metasegmentos
em um espao virtual mmapped. Os
Classloaders 1 e 3 representam a reflexo ou classloaders annimos e
empregam segmentos de tamanhos
especficos. Os Classloaders 2 e 4
podem ser empregados em segmentos de tamanho pequeno ou mdio,
baseado no nmero de itens em seus
carregadores.

Otimizao e Metaspace
Como mencionado anteriormente, uma VM Metaspace gerenciar
o crescimento do Metaspace, mas
talvez surgiro cenrios em que se
deseje limitar o crescimento atravs
do uso da configurao explcita do
-XX:MaxMetaspaceSize via linha de
comando. Por padro, o -XX:MaxMetaspaceSize no possui um limite,

ento, tecnicamente, o tamanho do


Metaspace poderia assumir o espao
de swap, e comearia a gerar falhas de
alocao nativa.
Para uma JVM servidora de 64 bits,
o valor padro/inicial do -XX:MetaspaceSize de 21MB. Esta a configurao do limite mximo inicial. Uma
que vez que esta marca alcanada,
uma varredura de lixo completa
disparada para descarregar classes
(quando os seus classloaders no estiverem mais ativos), e o limite mximo
reiniciado. O novo valor deste limite
depende da quantidade de Metaspace
liberado. Se o espao liberado no for
suficiente, o limite aumenta; se for liberado espao demais, o limite diminui. Isto ser repetido diversas vezes
se o limite inicial for muito baixo, e
ser possvel constatar a repetida coleta de lixo completa nos logs de co-

leta de lixo. Em tal cenrio, recebe-se


o aviso para configurar o -XX:MetaspaceSize para um valor mais elevado
atravs da linha de comando, para
evitar as coletas de lixo iniciais.
Aps coletas subsequentes, a VM
Metaspace ser automaticamente
ajustada para o limite mais alto, de
modo a postergar a coleta de lixo do
Metaspace.
H tambm duas opes: -XX:MinMetaspaceFreeRatio e -XX:MaxMetaspaceFreeRatio, que so anlogas aos
parmetros do GC FreeRatio e podem
ser configurados atravs da linha de
comando.
Algumas ferramentas foram modificadas para ajudar a obter mais
informaes sobre o Metaspace, e so
listadas a seguir:

eMag | Java: Presente e Futuro

jmap -clstats <PID>: exibe as estatsticas de um classloader. (Isto agora assume o lugar do -permstat, que era usado
para exibir estatsticas do classloader de JVMs anteriores ao JDK8). Segue um exemplo de sada no momento de
execuo do benchmark da DaCapo Avrora:

$ jmap -clstats <PID>


Attaching to process ID 6476, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.5-b02
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.liveness analysis may be inaccurate ...
class_loader classes
bytes parent_loader
alive? type
<bootstrap>
655
0x000000074004a6c0
0x000000074004a760
0x00000007401189c8
0x000000074004a708
0x00000007400752f8
total = 6
1310

1222734
0
0
0
0
1
1471
116 316053
538 773854
2314112

null
live
<internal>
0x000000074004a708
dead
null
dead
0x00000007400752f8
dead
0x000000074004a760
dead
0x000000074004a708
dead
N/A
alive=1, dead=5

java/util/ResourceBundle$RBClassLoader@0x00000007c0053e20
sun/misc/Launcher$ExtClassLoader@0x00000007c002d248
sun/reflect/DelegatingClassLoader@0x00000007c0009870
sun/misc/Launcher$AppClassLoader@0x00000007c0038190
org/dacapo/harness/DacapoClassLoader@0x00000007c00638b0
N/A

jstat -gc <LVMID>: agora exibe informaes do Metaspace, como demonstra o exemplo a seguir:

$jstat-gc <LVMID>
SOC
SIC
SOU S1U EC
EU
OC
OU
MC
UM
CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 96.0 6144.0 2456.3 129536.0 2228.3 7296.0 6550.3 896.0 787.0 229 0.211 33 0.347 0.558
Where, MC: Current Metaspace Capacity (KB); UM: Metaspace Utilization (KB)

jcmd <PID> GC.class_stats: Este um novo comando de diagnstico que permite ao usurio final se conectar
JVM em execuo, e obter um histograma detalhado dos metadados das classes Java.

Nota: Com o JDK8 build 13, voc deve iniciar o Java com -XX:+UnlockDiagnosticVMOptions.
$ jcmd <PID> help GC.class_stats
9522:
GC.class_stats
Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions.
Impact: High: Depends on Java heap size and content.
Syntax : GC.class_stats [options] [<columns>]
Arguments:

columns : [optional] Comma-separated list of all the columns to show. If not specified, the following columns are shown:
InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total (STRING, no default value)
Options: (options must be specified using the <key> or <key>=<value> syntax)

-all : [optional] Show all columns (BOOLEAN, false)

-csv : [optional] Print in CSV (comma-separated values) format for spreadsheets (BOOLEAN, false)

-help : [optional] Show meaning of all the columns (BOOLEAN, false)

InfoQ Brasil

Um exemplo de sada:
$ jcmd <PID> GC.class_stats
7140:
Index Super InstBytes KlassBytes annotations

CpAll MethodCount Bytecodes MethodAll

ROAll

RWAll

Total ClassName

-1

426416

480

24

576

600 [C

-1

290136

480

40

576

616 [Lavro-

576

600 [B

ra.arch.legacy.LegacyInstr;

-1

269840

480

43

137856

648

19248

129

43

136968

624

8760

94

43

75872

1296

560

24

4886

25288

16368

30568

46936 java.lang.Class

4570

33616

12072

32000

44072 java.lang.String

149

1400

880

2680

1480

528

2488

3016 avrora.sim.util.

31

440

280

1536

1816 avrora.

24

576

600 [Ljava.

3560 java.

util.HashMap$Node

836

57408

608

720

69

MulticastFSMProbe

43

55488

504

53712

480

680

sim.FiniteStateMachine$State

-1

10

-1

49424

480

11

-1

49248

480

24

576

600 [I

24

576

600 [Lavrora.sim.pla-

32

576

608 [Ljava.util.HashMa-

1216

432

2080

2512 avrora.sim.AtmelIn-

lang.Object;

tform.ExternalFlash$Page;
12

-1

24400

480

394

21408

520

600

33

19800

672

968

71

1240

664

2472

3136 avrora.arch.legacy.

152

104

1024

1128 sun.util.resources.

p$Node;
13

terpreter$IORegBehavior
14

727

LegacyInstr$MOVW
<snipped>
<snipped>
1299

1300

608

256

608

1744

10

290

1808

1176

3208

4384 sun.util.resources.

616

2184

12

395

2200

1480

3800

5280 sun.util.resources.

LocaleNamesBundle
1300

1098

OpenListResourceBundle
1301

1098

ParallelListResourceBundle
2244312

794288
34.0%

2024 2260976

12.1%

Index Super InstBytes KlassBytes annotations


0.0%

12801
34.3%

561882

3135144 1906688 4684704 6591392 Total


8.5%

CpAll MethodCount Bytecodes MethodAll

ROAll

47.6%

28.9%

RWAll

Total ClassName

71.1%

100.0%

Questes Atuais
Como mencionado anteriormente, a VM Metaspace emprega um alocador de segmentos. H mltiplos tamanhos de
segmentos, dependendo do tipo de classloader. Alm disso, os itens de classe por si mesmos no possuem um tamanho
fixo, por isso h chances de que os segmentos livres no sejam do mesmo tamanho que os segmentos necessrios para os
itens de classe. Tudo isso pode gerar uma fragmentao. A VM Metaspace (ainda) no utiliza compactao, consequentemente a fragmentao uma das principais preocupaes neste momento.

eMag | Java: Presente e Futuro

Sobre a Autora
Acompanhe Monica no Twitter:
@mon_beck.
Monica Beckwith uma engenheira de desempenho
trabalhando na indstria de hardware por mais de uma
dcada. Seu mais atual ttulo Arquiteta de Desempenho
na Servergy - uma startup que oferece uma nova classe de
servidores Cleantech hiper-eficientes . Antes da Servergy,
Monica trabalhou na Oracle / Sun e AMD otimizando a JVM
para sistemas de classe de servidor. Monica foi eleita uma
palestrante estrela do rock no JavaOne 2013.

10 InfoQ Brasil

8 FUNCIONALIDADES POUCO
CONHECIDAS DO JAVA 8
por Tal Weiss, traduzido por Vitor Puente
Este artigo visa apresentar algumas das novas APIs do Java 8 que no esto sendo to comentadas, mas que tornaram o Java melhor de vrias
maneiras.

1. StampedLock
O cdigo multithreaded tem sido um desafio para os
desenvolvedores. Com o tempo, algumas construes
complexas foram adicionadas s bibliotecas Java visando
auxiliar o desenvolvedor com cdigos multithreaded, e
seu acesso a recursos compartilhados. Um exemplo o
ReadWriteLock, que permite ao desenvolvedor dividir o
cdigo em sees que precisam ser mutuamente exclusivas (writers) e sees que no precisam (readers).
Na teoria parece timo. Porm um problema com ReadWriteLock que a aplicao pode ficar muito lenta, s
vezes at dez vezes mais lenta. O Java 8 introduziu um
novo bloqueio ReadWrite, chamado StampedLock. A boa
notcia que o StampedLock muito rpido. A m notcia
que mais complicado de usar e envolve mais estados. O
StampedLock no reentrante, o que significa que uma

thread pode causar um deadlock envolvendo ela mesma.


O StampedLock possui o modo otimista, que emite
uma marcao (stamp) retornada por cada operao de
bloqueio (lock). Essa marcao utilizada como uma espcie de ingresso. Cada operao de desbloqueio (unlock) precisa gerar sua marcao correspondente. Qualquer
thread que adquirir o bloqueio de escrita, enquanto outra
thread est com o bloqueio de escrita do modo otimista,
far com que o unlock seja invalidado (o stamp no ser
mais vlido). Nesse ponto, a aplicao pode comear tudo
novamente, possivelmente com um lock no modo pessimista, que tambm implementado pelo StampedLock.
O gerenciamento de tudo isso fica por conta do desenvolvedor. E como um stamp no pode ser utilizado para desbloquear outro, deve-se tomar cuidado.
Veja a seguir um exemplo deste tipo de lock em ao:

eMag | Java: Presente e Futuro 11

long stamp = lock.tryOptimisticRead(); //sem caminho bloqueante - muito rpido.


work (); // esperado que no ocorra nenhuma escrita por hora.
if (lock.validate(stamp)){
//sucesso! Sem conteno com a thread de escrita.
} else {
//outra thread precisa obter um bloqueio de escrita entretanto mudando o stamp.
//voltando a ter um bloqueio de leitura mais pesado.
stamp = lock.readLock(); //Este uma operao de leitura que causa o lock.
try {
//Sem escrita acontecendo agora.
work();
} finally {
lock.unlock(stamp); // Liberao do stamp utilizado.
}
}

2. Adicionadores concorrentes

3. Ordenao Paralela

Outra novidade do Java 8 lida especificamente


com cdigo escalvel: os Adicionadores Concorrentes (Concurrent Adders). Um dos padres mais bsicos de concorrncia a leitura e escrita de contadores
numricos. H diversas maneiras de fazer isso hoje
em dia, mas nenhuma to eficiente ou elegante como
a existente no Java 8.
Antes do Java 8, isso era feito utilizando Atomics,
que utilizavam instrues diretas da CPU de comparao e swap (CAS), atravs da classe sun.misc.Unsafe, para realizar a tentativa e marcar o valor de um
contador. O problema era que quando um CAS falhava devido a uma conteno, o AtomicInteger ficava
em loop, tentando continuamente o CAS em um loop
infinito, at o seu sucesso. Em altos nveis de conteno isso poderia se mostrar muito lento.
A partir do Java 8 foi adicionado o LongAdders.
Esse conjunto de classes fornece uma maneira conveniente de leitura e escrita de valores numricos
em cenrios de grande escalabilidade. A utilizao
simples. Basta iniciar um novo LongAdder e utilizar
os seus mtodos add() e intValue() para aumentar e
retornar o contador.
A diferena entre esta verso do Atomics e a antiga que, quando o CAS falha devido a alguma
conteno, em vez de fazer o giro na CPU, o Adder
armazenar o delta em uma clula interna alocada
para aquela thread. Ento adicionar o valor junto de
qualquer outro valor de clulas pendentes ao resultado do mtodo intValue(). Isso reduz a necessidade
de voltar e realizar o CAS novamente, ou bloquear
outras threads.
A utilizao do modelo de Adicionadores concorrentes deve ser sempre preferido frente ao modelo
Atmico para o gerenciamento de contadores.

Assim como os Adicionadores aceleram os contadores, o Java 8 traz uma maneira concisa de acelerar a
ordenao. E de uma maneira muito simples, em vez
de realizar a ordenao desta maneira:
Array.sort(myArray);
Agora pode utilizar o mtodo pronto para a paralelizao:
Arrays.parallelSort(myArray);
Isso automaticamente dividir a sua coleo em
partes, as quais sero ordenadas atravs de um nmero de cores e ento agrupadas novamente. H
uma ressalva, quando o mtodo de ordenao paralela chamado em ambientes com multi-thread elevado, tal como um web container sobrecarregado, os
benefcios iniciais so reduzidos, at mais de 90%, devido ao aumento de trocas de contexto da CPU.

12 InfoQ Brasil

4. Migrando para nova API de data


O Java 8 introduz uma nova API de datas. Uma
nova maneira de lidar com horas e a maioria dos mtodos da verso atual esto marcados como obsoletos.
A nova API traz a facilidade de uso e a preciso fornecidas pela popular API Joda Time para o ncleo da
biblioteca Java.
Assim como em qualquer nova API, as boas novas
so o estilo mais elegante e funcional. Infelizmente,
muito j foi feito com a antiga API e a transio dever levar tempo.
Para ajudar na transio, a classe Date possui um
novo mtodo chamado toInstant(), que converte
uma data para a nova representao. Isso especialmente til ao fazer uso de APIs que recebe o formato
clssico de data, pois basta converter a data para o
novo formato e utilizar todos os benefcios da nova
API de datas.

5. Controle de processos do sistema


operacional
Lanar um processo do sistema operacional diretamente do cdigo Java j possvel atravs das
chamadas Java Native Interface (JNI), mas com isso
bem provvel se deparar com resultados inesperados
ou excees srias mais para a frente. Ainda assim,
um mal necessrio.
Alm disso, os processos tm mais um lado desagradvel o fato de tenderem a ficar suspensos. O
problema ao iniciar um processo a partir do cdigo
Java at a verso 7 tem sido difcil o controle sobre um
processo uma vez iniciado.
Para ajudar nessa tarefa o Java 8 traz trs novos
mtodos na classe Process:
1. destroyForcibly() termina um processo com
um grau de sucesso bem maior do que antes;
2. isAlive() informa se um processo iniciado ainda
est vivo;
3. Uma nova sobrecarga de waitFor() especifica a
quantidade de tempo para que o processo termine.
Isso retorna ou o sucesso da execuo ou o time-out,
neste ltimo caso possvel terminar o processo.
Duas boas utilizaes para estes mtodos so:
Caso um processo no termine no tempo determinado, forar seu trmino e seguir em diante:
if (process.wait(MY_TIMEOUT, TimeUnit.MILLISECONDS)){
//success!
} else {
process.destroyForcibly();
}

Garantir que, antes que um cdigo termine, no


seja deixado nenhum processo para trs. Processos suspensos certamente esgotaro seu sistema
operacional, mesmo que lentamente.

for (Process p : processes) {


if (p.isAlive()) {
p.destroyForcibly();
}
}

6. Operaes numricas precisas


Um overflow numrico pode causar alguns dos
mais estranhos problemas em software, dada sua
caracterstica implcita. Isso especialmente verdade em sistemas que possuem contadores inteiros incrementados de acordo com o tempo. Nesses casos,

recursos que funcionam corretamente em pr-produo, podem comear a se comportarem de maneira


completamente estranha de repente, quando as operaes sofrem o overflow e produzem valores inesperados.
Para auxiliar nesse problema, o Java 8 adicionou
diversos mtodos exact classe Math, protegendo
um cdigo suscetvel a overflows, atravs do lanamento de uncheckedArithmeticException quando
o valor de uma operao causa um overflow.
int safeC = Math.multiplyExact(bigA, bigB);
// Ser lanada uma ArithmeticException caso o
resultado exceda +-2^31

O nico aspecto negativo disso que a responsabilidade em identificar como o cdigo pode ter problemas com overflow fica por conta de quem est desenvolvendo. No h soluo mgica, porm isso j
melhor que nada.

7. Gerao segura de nmeros aleatrios


O Java tem sido criticado por anos pelos problemas de segurana. Justo ou no, um grande esforo
tem sido feito para blindar a JVM e os frameworks de
possveis ataques. Os nmeros aleatrios com baixo
nvel de entropia tornam sistemas que os utilizem na
criao de chaves para criptografia ou cdigos hash
mais suscetveis a ataques.
At o momento, a escolha do algoritmo de gerao
de nmeros aleatrios de responsabilidade do desenvolvedor. O problema que, nas implementaes
que dependem de um hardware, sistema operacional
ou JVM especficos, o algoritmo desejado pode no
estar disponvel. Em tais casos, as aplicaes tm tendncia a migrar para verses mais fracas de geradores, o que aumenta o risco de ataques.
O Java 8 adicionou o novo mtodo SecureRandom.
getInstancStrong() com o objetivo de permitir que a
JVM escolha uma verso segura. Se escrever cdigo
sem o completo controle sobre o hardware/SO/JVM
em que ser executado, deve-se considerar o uso deste mtodo. ( uma situao comum quando se constroem aplicaes a serem executadas na nuvem ou
em ambientes de PaaS.)

8. Referncias opcionais
As excees do tipo NullPointerException so bem
antigas. Porm ainda hoje esto presentes no dia-a-dia de uma equipe de desenvolvimento, no importa
quo experiente a equipe seja. Para ajudar com este

eMag | Java: Presente e Futuro 13

problema o Java 8 introduz um novo template chamado Optional<T>.


Baseado em linguagens como Scala e Haskell, esse
template indica explicitamente quando uma referncia passada ou retornada por uma funo pode ser
nula. Isso ajuda a reduzir as dvidas se uma referncia pode ou no ser nula, devido confiana em documentaes que podem estar desatualizadas, ou a
cdigos que podem mudam com o tempo.
Optional<User> tryFindUser(int userID) {
ou
void
processUser(User
user,
Optional<Cart>
shoppingCart) {

O template Optional possui funes que tornam


o trabalho mais conveniente, como isPresent() que
verifica se um valor no-nulo est disponvel, ou
ifPresent(), que recebe uma funo Lambda que
ser executada caso isPresent() seja verdadeiro. O
lado negativo , assim como ocorre com a nova API
de Data e Hora, levar tempo at que est novidade
esteja presente nas diversas APIs usadas diariamente.
Aqui est a nova sintaxe Lambda para escrever um
valor opcional:
value.ifPresent(System.out::print);

Sobre o Autor
Tal Weiss o CEO da Takipi. Weiss vem desenhando aplicaes escalveis, de tempo real em Java e C++ nos ltimos 15 anos. Ele ainda gosta de
analisar um bom bug atravs da instrumentao de cdigo Java. Em seu
tempo livre Weiss toca Jazz na bateria.

14 InfoQ Brasil

ANOTAES DE TIPOS NO JAVA 8: FERRAMENTAS


Epor Todd
OPORTUNIDADES
Schiller, traduzido por Wellington Pinheiro
As anotaes no Java 8 podem ser escritas no apenas em declaraes, mas tambm em qualquer uso de tipos como nas declaraes, generics e
converses de tipos (cast). Nesse artigo so apresentadas as anotaes de tipos e as ferramentas que ajudam a construir aplicaes melhores.

as verses anteriores do Java era possvel anotar


somente declaraes. Com o Java 8 as anotaes
podem ser escritas em qualquer local que os tipos so usados, como por exemplo: declaraes, generics
e converses de tipos (casts), como apresentado no cdigo
a seguir:
@Encrypted String data;
List<@NonNull String> strings;
myGraph = (@Immutable Graph) tmpGraph;

primeira vista, as anotaes de tipo no aparentam


ser uma das funcionalidades mais atraentes dessa nova
verso do Java. Ao contrrio, em relao linguagem em
si, as anotaes possuem somente uma sintaxe e as ferramentas que do a sua semntica, isto , significado e
comportamento.
Como desenvolvedor Java, provvel que as anotaes
j estejam sendo utilizadas para melhorar a qualidade do
software. Considere a anotao @Override, introduzida

no Java 1.5. Em projetos com muitas heranas no triviais,


torna-se difcil rastrear qual implementao de um mtodo ser executado. Nesse contexto, se no forem tomados
os devidos cuidados ao modificar a assinatura de um mtodo, isso pode fazer com que o mtodo de uma subclasse
deixe de ser executado, pois ele deixar de sobrescrever
o mtodo da superclasse recm alterado. Eliminar a chamada de um mtodo dessa forma pode introduzir uma
falha ou alguma vulnerabilidade. Em decorrncia disso,
a anotao @Override foi introduzida. Ela permite que
os desenvolvedores deixem explcito os mtodos que sobrescrevem outros mtodos da superclasse. O compilador
Java usa essa informao para advertir o desenvolvedor
quando o cdigo no reflete essa inteno. Usando essa
abordagem, as anotaes agem como um mecanismo
para auxiliar na verificao automtica do programa.
Alm da verificao automtica, as anotaes tm desempenhado um papel central para aumentar a produtividade atravs de tcnicas de metaprogramao. A ideia
que as anotaes podem informar as ferramentas sobre

eMag | Java: Presente e Futuro 15

como gerar cdigo auxiliar, fazer transformaes no


cdigo ou definir como o programa dever se comportar em tempo de execuo. Por exemplo a API de
persistncia JPA (Java Persistence API), introduzida
no Java 1.5, permite que os desenvolvedores especifiquem de forma declarativa uma correspondncia entre objetos Java e entidades do banco de dados atravs
de anotaes, tal como: @Entity. Ferramentas como o
Hibernate podem usar essas anotaes para fazer mapeamentos e consultas SQL em tempo de execuo.
No caso do JPA e do Hibernate, as anotaes so
usadas para evitar a escrita de cdigo repetitivo, reduzindo assim a duplicidade de cdigo - princpio conhecido como No Se Repita (Dont Repeat Yourself
- DRY). Curiosamente, sempre que se olha para as ferramentas que auxiliam na aplicao de boas prticas,
no difcil encontrar o uso de anotaes. Alguns
exemplos notveis ajudam na reduo do acoplamento atravs da Injeo de Dependncia e tambm na
separao de responsabilidades com a Programao
Orientada a Aspectos
Mas se as anotaes j esto sendo usadas para
melhorar a qualidade do cdigo, por que usar anotaes de tipos?
Uma resposta simples que as anotaes de tipos trazem mais possibilidades. Elas permitem, por
exemplo, que mais tipos de falhas sejam detectados
automaticamente e do mais controle s ferramentas
de produtividade.

Sintaxe das anotaes de tipo


As anotaes de tipo no Java 8 podem ser escritas
em qualquer local em que um tipo usado, como por
exemplo:
@Encrypted String data
List<@NonNull String> strings

tao pode ser aplicada em qualquer ponto que um


tipo usado, por exemplo em declaraes, generics e
converses de tipos (casts). O cdigo a seguir exemplifica alguns dos usos desses tipos de anotaes:
@TypeUse class MyClass<@TypeParameter T extends @TypeUse
Integer> {
@TypeUse <@TypeParameter S> MyClass(String s) {
...
}
public static void main(String ... args) {
Object o = ( @TypeUse String ) new String( Test );
if( o instanceof @TypeUse String ){
...
}
}
}

Assim como as anotaes em declaraes, as


anotaes de tipos podem ser salvas junto com
o arquivo de bytecode gerado e acessadas em
tempo de execuo via reflection atravs das
polticas de reteno: RetentionPolicy.CLASS ou
RetentionPolicy.RUNTIME, usadas na definio
da anotao. Existem duas diferenas fundamentais
entre as anotaes de tipo e as suas predecessoras.
Primeiro, as anotaes de tipo aplicadas a variveis
locais podem ser salvas junto com o bytecode.
Segundo, o tipo usado com generics tambm salvo
e fica acessvel em tempo de execuo.
Embora as anotaes fiquem disponveis em tempo de execuo, elas no afetam a execuo do programa. Por exemplo, um desenvolvedor pode declarar duas variveis do tipo File e uma varivel do
tipo Connection no corpo de um mtodo, da seguinte
forma:
File file = new File(aFile);
@Encrypted File encryptedFile = new File(anEncryptedFile);
@Open Connection connection = getConnection();

MyGraph = (@Immutable Graph) tmpGraph;

Criar uma anotao de tipo muito simples,


basta usar o ElementType.TYPE_PARAMETER,
ElementType.TYPE_USE ou ambos, na definio do
alvo (target) da anotao.

Supondo que a classe Connection tenha um mtodo send(File), possvel executar esse mtodo passando como parmetro qualquer uma das duas variveis do tipo File:
connection.send(file);

@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})

connection.send(encryptedFile);

public @interface Encrypted { }

O ElementType.TYPE_PARAMETER indica que


a anotao pode ser usada na declarao de tipos, tais
como: classes ou mtodos com generics ou ainda junto de caracteres coringa em declaraes de tipos annimos. O ElementType.TYPE_USE indica que a ano-

16 InfoQ Brasil

Como era de se esperar, a ausncia de efeito em


tempo de execuo implica que, embora os tipos possam ser anotados, os mtodos no podem ser sobrecarregados com base nas anotaes dos tipos.
public class Connection{

void send(@Encrypted File file) { ... }


// A tentativa de sobrecarga a seguir resulta em um erro
de compilao
// void send( File file) { ... }
. . .
}

A intuio por trs dessa limitao que o compilador no tem conhecimento sobre a relao entre
tipos anotados e no anotados ou entre tipos com diferentes anotaes.
Repare que h uma anotao @Encrypted na varivel encryptedFile coincidindo com o parmetro
file na assinatura do mtodo send, mas perceba que
no h nada nesse mtodo que corresponda anotao @Open na varivel connection. Quando feita a
chamada connection.send(...), a varivel connection
conhecida como uma receptora (receiver) do mtodo
(o termo receiver uma analogia clssica troca de
mensagens entre objetos na teoria de Orientao a
Objetos). O Java 8 introduz uma nova sintaxe para as
declaraes de mtodos de forma que anotaes de
tipos possam ser escritas em um receptor no mtodo.
void send(@Open Connection this, @Encrypted File file)

Observe nesse ltimo exemplo a sintaxe para definir o mtodo send. O primeiro parmetro na verdade
faz referncia instncia receptora, por isso o nome
desse parmetro this.
Como citado anteriormente, as anotaes no afetam a execuo do programa. Assim, um mtodo
declarado com a nova sintaxe do parmetro receptor
tem o mesmo comportamento quele utilizando a
sintaxe tradicional. Na prtica, o uso da nova sintaxe
s permite que anotaes de tipos sejam escritas no
tipo do receptor.
Uma explicao completa da sintaxe de anotaes
de tipos, incluindo sintaxe para arrays multi-dimensionais, pode ser encontrada na especificao JSR
(Java Specification Request) 308.

compilado, executado e causar erro durante a execuo. O compilador Java no faz verificaes de anotaes definidas pelo usurio. Apesar disso, a plataforma Java expe duas APIs que auxiliam nessa tarefa,
uma para a criao de plugins para o Compilador e
outra para o processamento de anotaes, de forma
que terceiros possam construir seus prprios mtodos de anlise.
Nos exemplos anteriores, as anotaes tinham a
funo de qualificar os valores que as variveis poderiam conter. Porm, podem ser pensadas outras
formas de qualificar o tipo File: @Open, @Localized,
@NonNull, etc; tambm pode ser pensada na aplicao dessas anotaes qualificando outros tipos, como
por exemplo: @Encrypted String. Devido ao fato das
anotaes serem independentes do sistema de tipos
do Java, os conceitos expressos atravs delas podem
ser reutilizadas de muitas formas.
Mas como essas anotaes poderiam ser automaticamente verificadas? Intuitivamente, algumas anotaes so subtipos de outras anotaes e suas aplicaes podem ser verificadas em relao aos tipos.
Considere a vulnerabilidade ao ataque de Injeo de
SQL, causado pela execuo de sentenas SQL modificadas maliciosamente pelo usurio. Pode-se pensar
em um tipo de dados classificado como @MaybeTainted, indicando que o dado pode ter sido adulterado,
ou @Untainted, indicando que o dado est garantidamente livre de adulterao, pois no foi diretamente
informado pelo usurio.
@MaybeTainted String userInput;
@Untainted String dbQuery;

Detectando erros com anotaes


Escrever anotaes no cdigo serve para enfatizar
erros quando o cdigo tem algum problema:
@Closed Connection connection = ...;
File file = ...;

connection.send(file); // Problema!: fechada e no


criptografada!

Contudo, esse ltimo cdigo de exemplo pode ser

A anotao @MaybeTainted pode ser vista como


um supertipo da anotao @Untainted. Existem vrias maneiras de pensar nessa relao. Primeiro, o
conjunto de valores que podem ter sido adulterados
podem ser um superconjunto de valores que sabidamente no foram adulterados (um valor que no foi
adulterado pode ser um elemento desse superconjunto). Dessa forma, a anotao @Untainted fornece uma
garantia maior que @MaybeTainted. Na prtica, essa

eMag | Java: Presente e Futuro 17

tipagem poderia funcionar da seguinte forma:


userInput = dbQuery; // OK
dbQuery = SELECT FROM * WHERE + userInput; // erro de
tipo!

Nesse exemplo, a primeira linha no contm nenhum problema, pois userInput supe que o valor
atribudo pode ter sido adulterado, mesmo que esse
no seja o caso. Por outro lado, essa tipagem revela
um erro na segunda linha, pois est atribuindo um
valor que pode ter sido adulterado a uma varivel
que contm essa restrio.

O framework Checker
O Checker um framework que faz verificaes de
anotaes em Java. Lanado em 2007, esse framework
um projeto de cdigo aberto encabeado pelo sub-lider da especificao JSR 308, professor Michael Ernst.
O Checker vem com um conjunto padro de anotaes e verificadores de falhas, tais como: NullPointerException, incompatibilidade no uso de unidades de
medidas, vulnerabilidades de segurana, problemas
de concorrncia, entre outros. Por ser um verificador
que utiliza mecanismos formais de verificao de tipagem baseado em lgica, ele capaz de reconhecer
falhas potenciais que verificadores baseados em heursticas no detectam. O framework usa uma API de
compilador que detecta as falhas durante a compilao. Outra caracterstica que ele estensvel, o prprio desenvolvedor pode criar rapidamente os seus
verificadores de anotaes para detectar problemas
especficos da aplicao em questo.
A meta do Checker detectar falhas sem que o
desenvolvedor tenha que escrever muitas anotaes.
Isso feito principalmente atravs de duas funcionalidades apelidadas como: padres mais inteligente e
controle de fluxo sensveis. Por exemplo, durante o
processo de verificao de falhas por ponteiros nulos, o verificador assume que os parmetros de um
mtodo no so nulos por padro. O verificador pode
tambm utilizar condicionais para determinar quando uma atribuio de nulo uma expresso vlida.
void nullSafe(Object nonNullByDefault, @Nullable Object
mightBeNull){
nonNullByDefault.hashCode(); // OK, devido ao padro
mightBeNull.hashCode(); // Falha!
if (mightBeNull != null){
mightBeBull.hashCode(); // OK, devido ao padro
}
}

18 InfoQ Brasil

Na prtica, os padres e o controle de fluxo sensveis significam que o desenvolvedor raramente ter
que escrever anotaes no corpo dos mtodos, pois o
verificador capaz de inferir e verificar as anotaes
automaticamente. Mantendo a semntica das anotaes fora do compilador oficial do Java garante que
ferramentas de terceiros e os prprios desenvolvedores tomem as suas decises. Isso permite que a verificao de erros possa ser personalizada conforme as
necessidades de cada projeto.
A habilidade de definir suas prprias anotaes
tambm permite que seja considerada a verificao
de subtipos especficos do domnio de negcio. Por
exemplo, em um sistema financeiro, as taxas de juros usam frequentemente porcentagens enquanto a
diferena entre taxas utiliza ponto base (1/100 de 1%).
Com um framework de verificao de unidades podem ser definidas as anotaes @Percent e @BasisPoint para garantir que no h confuso no uso dos
dois tipos:
BigDecimal pct = returnsPct(...); // anotado para devolver @Percent
requiresBps(pct); // erro: requer @BasisPoints

No exemplo apresentado, devido ao fato do Checker ser sensvel ao fluxo de controle, sabe-se que
pct um @Percent BigDecimal quando feita a chamada para requiresBps(pct) com base em dois fatos:
returnsPct(...) anotado para devolver um @Percent
BigDecimal e pct no foi novamente atribudo antes
de chamar requireBps(...). Frequentemente, desenvolvedores usam convenes de nomes para tentar prevenir esses tipos de falha. O que o Checker faz dar
ao desenvolvedor a garantia de que essas falhas no
existam, mesmo que o cdigo mude e evolua.
O Checker j foi executado em milhes de linhas
de cdigo, apontando centenas de falhas, mesmo em
cdigo bem testado. Um dos exemplos mais interessante aconteceu ao execut-lo com a biblioteca muito
utilizada Google Collections, agora Google Guava,
que revelou um possvel NullPointerException que
no tinha sido detectado aps vrios testes e nem
aps utilizar ferramentas heursticas de anlise esttica de falhas.
Resultados assim foram obtidos sem fazer muitas
alteraes no cdigo existente. Na prtica, verificar
uma propriedade com o Checker requer somente 2
ou 3 anotaes para uma centena de linhas de cdigo.
Para aqueles que utilizam o Java 6 ou 7, tambm
possvel usar o Checker para melhorar a qualidade
do cdigo. As anotaes podem ser escritas em comentrios, tal como:

Apesar do Checker ser o melhor framework para


fazer verificao de falhas utilizando anotaes, ele
no o nico atualmente. Tanto o Eclipse quanto o
IntelliJ do suporte a esse tipo de anotao:

/* @NonNull */ String aString

Historicamente, a razo disso que o Checker foi


desenvolvido junto com a JSR 308, que teve incio em
2006.

POSSUEM SUPORTE
Checker Framework

Suporte completo, incluindo anotaes em comentrios.


Suporte verificao de valores no
nulos.
Podem ser escritos inspecionadores
personalizados, suporte verificao
de valores no nulos.

Eclipse
IntelliJ IDEA

NO POSSUEM SUPORTE
PMD
Coverity
Check Style
Find Bugs

Sem suporte para Java 8.


Sem suporte para Java 8.

Aumentando a produtividade com anotaes de tipo


A ideia inicial por trs das anotaes de tipo era a verificao de falhas. Contudo, ainda haviam muitas aplicaes convincentes desse tipo de anotao em ferramentas de produtividade. Para entender um pouco melhor
o porqu, considere os seguintes exemplos de como as anotaes so usadas

Programao Orientada a Aspectos


Injeo de Dependncia
Persistncia
As anotaes so especificaes declarativas para
informar como as ferramentas devem gerar cdigo
ou arquivos auxiliares e como as ferramentas devem
se comportar durante a execuo do programa. O uso
das anotaes desse modo pode ser considerado uma
forma de metaprogramao. Alguns frameworks, tal
como o Lombok, tiram vantagem da metaprogramao com anotaes ao extremo, resultando em um cdigo que mal parece Java.
Considere a Programao Orientada a Aspectos
(Aspect Oriented Programming - AOP). A AOP ajuda na separao de propriedades ortogonais de uma
aplicao, tais como log e autenticao, daquelas relacionadas s regras de negcio. Com a AOP possvel

@Aspect, @Pointcut, etc.


@Autowired, @Inject, etc.
@Entity, @Id, etc.
executar um aplicativo em tempo de compilao que
adiciona cdigo ao programa com base em um conjunto de regras. Por exemplo, pode ser definida uma
regra que automaticamente faz autenticao com
base no tipo anotado:
void showSecrets(@Authenticated User user){
// Inserido automaticamente pela AOP:
if (!AuthHelper.EnsureAuth(user)) throw . . .;
}

Como antes, a anotao est qualificando o tipo.


Ao invs de verificar as anotaes em tempo de compilao, a AOP usada para fazer a verificao em
tempo de execuo automaticamente. Esse ltimo

eMag | Java: Presente e Futuro 19

exemplo mostra a anotao de tipo sendo usada para


dar um controle maior sobre como e quando a AOP
modifica o programa.
O Java 8 tambm d suporte s anotaes de tipo
em declaraes locais que so persistidas nos arquivos de bytecode. Isso cria novas oportunidades para
se ter uma AOP mais granular. Por exemplo, para
incluir cdigo de rastreamento de uma forma mais
granular:
// Faz o rastreamento de todas as chamadas ao objeto ar
@Trace AuthorizationRequest ar = . . .;

Novamente, as anotaes de tipo do maior controle ao se fazer metraprogramao com AOP. A Injeo de Dependncia uma histria similar. Com o
Spring 4, finalmente possvel usar generics como
qualificador:
@Autowired private Store<Product> s1;
@Autowired private Store<Service> s2;

Com generics possvel eliminar a necessidade


introduzir classes como ProductStore e ServiceStore
ou usar regras mais frgeis de injeo baseada em
nomes.
Com anotaes de tipo, no difcil imaginar que
um dia o Spring permita us-las para controlar a injeo da seguinte forma:
@Autowired private Store<@Grocery Product> s3;

Esse exemplo mostra um tipo anotado servindo


como um mecanismo de separao de interesses, favorecendo para que a hierarquia de tipos do projeto
seja mais concisa. Essa separao s possvel porque as anotaes de tipo so independentes do sistema de tipagem do Java.

A estrada frente
Como apresentado, as anotaes de tipo podem
ser usadas tanto para detectar como prevenir erros
em programas e tambm para aumentar a produtividade. Contudo, o potencial real das anotaes de
tipos est em combinar a verificao de erros e a metaprogramao para dar suporte aos novos paradigmas de desenvolvimento.
A ideia bsica construir ambientes de execuo
e bibliotecas que alavanquem a abordagem de criar
programas automaticamente mais eficientes, paralelos ou seguros e que faam com que os desenvolvedores usem as anotaes corretamente.

20 InfoQ Brasil

Um bom exemplo dessa abordagem o framewok


EnerJ, de Adrian Sampson, para computao com
eficincia energtica utilizando a computao aproximada. EnerJ baseia-se na observao de que em certas
ocasies, tal como o processamento de imagens em
dispositivos mveis, faz sentido reduzir a preciso
para poupar energia. Um desenvolvedor usando o
EnerJ pode anotar um dado que no crtico usando a anotao @Approx. Com base nessa anotao, o
ambiente de execuo do EnerJ usa vrios atalhos ao
manipular esse dado. Por exemplo, pode ser utilizado um hardware de clculos aproximados de baixo
consumo de energia para armazenar e fazer clculos.
Contudo, tendo dados aproximados se movendo pelo
programa pode ser perigoso, e nenhum desenvolvedor vai querer controlar o fluxo afetado por esse dado
aproximado. Portanto, o EnerJ usa o Checker para garantir que os dados aproximados no sejam utilizados em sentenas de controle de fluxo, por exemplo,
em sentenas condicionais como ifs.
Mas as aplicaes dessa abordagem no so limitadas a dispositivos mveis. Em finanas, frequentemente h um conflito entre preciso e velocidade.
Nesses casos, o ambiente de execuo pode decidir
entre usar um algoritmo de Monte Carlo para o clculo de caminhos, um critrio de convergncia ou mesmo processar algo em um hardware especializado
com base nas demandas atuais ou na disponibilidade
de recursos.
A beleza desse abordagem que a preocupao de
como uma execuo deve ser feita fica fora da lgica
de negcio central da aplicao, que descreve o que
deve ser feito.

Concluso
No Java 8, as anotaes podem ser usadas em qualquer tipo, incrementando a capacidade de escrever anotaes em declaraes. As anotaes por s prprias no afetam o comportamento do programa. Contudo, utilizando ferramentas como o Checker, possvel utiliz-las para verificar automaticamente a ausncia de falhas e
aumentar a produtividade com metaprogramao. Enquanto ainda levar algum tempo para que as ferramentas
existentes obtenham total vantagem das anotaes de tipos, agora hora de comear a explorar como as anotaes de tipos podem melhorar tanto a qualidade do software desenvolvido quanto a produtividade.

Sobre o Autor
Todd Schiller diretor da FinLingua, uma companhia de consultoria
e desenvolvimento de software para a rea financeira. A prtica de
consultoria da FinLingua ajuda equipes de desenvolvimento a adotar
uma linguagem especfica de domnio, metraprogramao e tcnicas
de anlise de programas. Todd um membro ativo da comunidade de
pesquisa em engenharia de software; sua pesquisa em especificao e
verificao tem sido apresentada nas principais conferncias internacionais, incluindo ICSE e OOPSLA.

eMag | Java: Presente e Futuro 21

JAVA 8: DESMISTIFICANDO LAMBDAS

por Simon Ritter, traduzido por Rafael Sakurai

O artigo destaca os pontos principais da palestra Lambdas & Streams que Simon Ritter apresentou no QCon London 2014. Ele explica o que so as
expresses Lambdas, interface funcional, referncia de mtodos, Streams, operaes de agregao e diversos exemplos

e perguntarmos aos desenvolvedores Java sobre o


Java 8, teremos diversas respostas bem animadas,
especialmente sobre o uso das expresses lambda.
Mas aps uma conversa mais honesta, encontramos
um fervor misturado com um pouco de receio em relao
s novas e misteriosas APIs disponveis na Web. Simon
Ritter revelou alguns dos mistrios na apresentao sobre
lambdas na conferncia QCon London 2014.
A seguir, temos um trecho de cdigo Java que ilustra
um padro comum:
Nota: As partes em vermelho so aquelas que estamos
interessados; e as partes em azul representam cdigo re-

22 InfoQ Brasil

petitivo.
Neste problema, queremos encontrar a maior nota em
uma coleo de estudantes. Usamos um idioma comum
de iterao externa para percorrer e comparar cada elemento da coleo.
Mas h algumas desvantagens no cdigo. Em primeiro
lugar, a iterao externa significa que os desenvolvedores
so responsveis pela implementao (programao imperativa), e como usado um nico loop, definimos que
a execuo do cdigo ser de modo sequencial. Se quisermos otimiz-lo, no poderamos facilmente segmentar
em um conjunto de execuo de instrues em paralelo.
Em segundo lugar, a varivel highestScore mutvel
e no thread-safe. Ento, mesmo que quisssemos quebr-lo em mltiplas threads, precisaramos adicionar um
lock (bloqueio) para prevenir race conditions (condies
de concorrncia), que por sua vez podem introduzir problemas de desempenho.
Agora, se quisermos agir de modo mais inteligente,
podemos mudar um pouco mais a implementao em
direo ao estilo funcional utilizando uma classe interna
annima:

Nessa implementao, eliminamos o estado mutvel e passamos o trabalho da interao para a biblioteca. Estamos encadeando uma sequncia de chamadas de mtodos para aplicar a operao em uma
expresso Olhe para todos os meus estudantes e filtre apenas aqueles que se graduaram em 2011.
A classe interna annima implementa a interface
Predicate (ela contm um mtodo, aceita um parmetro e retorna um valor booleano) com o mtodo cha-

Pense nas expresses lambda como um mtodo,


no sentido de que ele aceita parmetros, tem corpo e
retorna um tipo esttico.
Nesse exemplo, usamos as expresses lambda
para obter o mesmo algoritmo que determina qual a
maior nota, como nos exemplos anteriores. Vejamos
em detalhes.
Primeiro, criamos um Stream a partir de uma Collection. O mtodo stream novo na interface Collection e funciona de forma parecida com um Iterator
embutido (veremos em mais detalhes logo adiante).
O stream prepara os resultados da coleo, que ento passa para o mtodo filter, descrevendo como
as partes sero filtradas usando a expresso lambda
que compara o ano de graduao dos estudantes com

mado op, que simplesmente compara o ano de graduao do estudante com 2011 e retorna o resultado.
Enviaremos o resultado (todos os estudantes graduados em 2011) para o mtodo map, que usar outra classe interna annima para chamar um mtodo
da interface de mapeamento com seu nico mtodo
extract para extrair o dado que queremos (chamando o mtodo getScore). Ento passaremos esse resultado, que um conjunto de notas de todos estudantes
graduados em 2011, para o mtodo max, que enfim
entregar o maior valor a partir do conjunto de resultados.
Usando essa abordagem, tratamos toda a interao, filtro e acmulo com o uso da biblioteca, sem
precisar fazer isso de forma explcita. Isso no somente simplifica a implementao, como tambm elimina
o compartilhamento de estado, deixando mais fcil
pedir ao cdigo da biblioteca para decompor a implementao em diversas sub tarefas e aloc-lo em diferentes threads para serem executadas em paralelo.
Em muitos casos, tambm executamos uma avaliao
posterior, economizando ainda mais tempo.
Ento, uma abordagem que usa classe interna
annima rpida e thread-safe, mas atente-se para
as cores do cdigo fonte. Note que a quantidade em
azul maior do que em vermelho, indicando cdigo
repetitivo.
Ento, entram em cena as expresses lambda!

2011.
Note que no h um retorno explicito. Simplesmente dizemos Compare o ano de graduao com
2011 e o compilador deduz que destina-se a interface
Predicate (que tem um nico mtodo que necessita de
uma assinatura com um retorno do tipo booleano).
O mtodo map processado de forma similar, usando uma expresso lambda, passando um estudante S
como parmetro e mapeando (como um tradutor) seu
valor de retorno, que a nota (score) do estudante. O
mtodo map no deve ser confundido com o java.util.
Map que usa pares de chave-valor. O mtodo map da
classe Stream retorna uma nova instncia do Stream
contendo os resultados da operao aplicada para todos os elementos da Stream de entrada, produzindo,

eMag | Java: Presente e Futuro 23

nesse caso, um Stream com todas as notas.


Usando lambdas implementamos o mesmo algoritmo com muito menos cdigo. mais compreensvel, portanto menos propenso a erros, e como visto,
ele pode ser alterado para um algoritmo paralelo uma
vez que no h compartilhamento de estado.
Como Ritter disse em sua apresentao:

As expresses Lambda representam uma funo


annima. Ento, elas so como mtodos, mas no so
realmente um mtodo. Elas so como funes annimas no sentido de que elas tem as mesmas funcionalidades de um m todo, mas elas no so mtodos
porque no esto associadas com uma classe. Se pensar no Java como programamos hoje, criamos classes
e classes tm mtodos. Portanto o mtodo tem uma
classe associada a ele. No caso das expresses Lambd
dentro de uma expresso Lambda e ela tem um corpo,
que defini o que ela far. Tambm possvel fazer as
mesmas coisas que um mtodo: pode agrupar instrues; pode usar chaves e ter mltiplas instrues sem
nenhum problema. A coisa mais importante sobre isso
que agora permite usar uma maneira simples de ter
um procedimento parametrizado, no apenas valores

o compilador identifica pela estrutura. O compilador


pode determinar a interface funcional representada a
partir de sua posio. O tipo de uma expresso lambda o da interface funcional associada.
Como o compilador conhece os locais que so usados uma expresso lambda, possvel determinar
muito sobre essa expresso. Portanto como o compilador sabe o tipo da interface funcional, ento pode
inferir os outros tipos necessrios.
Mas, Ritter avisa:
Um ponto de ateno que embora no tenhamos
explicitamente colocado o tipo da informao l, isso
no significa que est usando uma tipagem dinmica
no Java. Nunca faramos isso, desagradvel e ruim.
Ento, o que fazemos dizer que isso ainda uma tipagem muito esttica, mas com menos digitao.
Ainda segundo Ritter, uma coisa que diferencia as
expresses lambda dos closures, que ao contrrio
dos closures, as lambdas no podem acessar as variveis que esto fora da expresso lambda, exceto as
variveis que so efetivamente final, isso significa que
embora a varivel no precisa da palavra-chave final
(ao contrrio de uma classe interna), no entanto o seu
valor no pode ser reatribudo.

parametrizados.
Ritter ampliou esse conceito apontando que uma
vez que uma lambda uma funo sem uma classe,
ento a palavra-chave this no se refere a prpria
lambda, mas sim a classe na qual foi declarada. Isso
distingue de uma classe interna annima, na qual
this refere-se a prpria classe interna.
til olhar para as decises de implementaes
que os designers da linguagem fizeram para desenvolver os lambdas.
Olhando para o Java como um todo, h muitas interfaces que possuem apenas um mtodo.
Vamos definir uma interface funcional como uma
interface com exatamente um mtodo abstrato, por
exemplo:
interface
interface
interface
interface
interface

Comparator<T> { boolean compare(T x, T y); }


FileFilter { boolean accept(File x); }
Runnable { void run(); }
ActionListener { void actionPerformed(); }
Callable<T> { T call(); }

Uma expresso Lambda permite definir uma interface funcional (novamente, um mtodo abstrato) que

24 InfoQ Brasil

Referncia de mtodos
A sintaxe da referncia de mtodo outra nova
funcionalidade da expresso lambda. um atalho
que permite reutilizar um mtodo basicamente como
uma expresso Lambda. Podemos fazer coisas como:
FileFilter x = f -> f.canRead();
Essa sintaxe diz para o programa criar um FileFilter que filtra os arquivos com base em uma propriedade comum nesse caso, se o arquivo pode ser lido.
Note que nesse exemplo, nunca mencionamos que f
um arquivo; o compilador infere atravs da assinatura do nico mtodo no FileFilter:
boolean accept(File pathname);
Podendo ser simplificado ainda mais usando a
nova notao do Java 8 ::.
FileFilter x = File::canRead;

Essas sintaxes so completamente equivalentes.


Para chamar um construtor de forma anloga,
pode ser utilizado a sintaxe ::new. Por exemplo, se
tivermos uma interface funcional como:
interface Factory<T> {
T make();
}

Ento, podemos dizer:

Operaes de agregao
Operaes de negcios frequentemente envolvem
agregaes como: encontrar a soma, mximo, ou mdia de um conjunto de dados, ou grupo de alguma
coisa. At agora, tais operaes so normalmente executadas com loops de interao externa, como dissemos, nos restringindo das otimizaes e adicionando
boilerplate ao cdigo fonte.
As Streams do Java SE 8 tem como objetivo resolver estes problemas. Nas palavras de Ritter:

Factory<List<String>> f = ArrayList<String>::new;

Um stream a maneira de abstrair e especificar


Isso equivalente a:
Factory<List<String>> f = () -> return new ArrayList<String>();

como processar uma agregao. Ele no uma estrutura de dados. Na realidade uma maneira de tratar os
dados, mas define uma nova estrutura de dados, e in-

E agora, quando f.make() chamada, ser retornado um novo ArrayList<String>.


Usando as interfaces funcionais, o compilador
pode deduzir muitas coisas sobre a tipagem e inteno, como demonstrado nesses exemplos.

teressantemente pode tanto finito quanto infinito. En-

Evoluo da biblioteca

infinito, posso continuar processando os dados para

Uma das vantagens das lambdas e expresso de


cdigos como dados que, como visto, as bibliotecas
existentes foram atualizadas para aceitar lambdas
como parmetros. Isso introduz alguma complexidade: como introduzir mtodos na interface sem quebrar as implementaes das interfaces que j existem?
Para fazer isso, o Java introduz o conceito de mtodos de extenso, tambm conhecido como defender
mtodos ou mtodos default (padro).
Vamos explicar usando um exemplo. O mtodo
stream foi adicionado na interface Collection para
fornecer um suporte bsico ao lambda. Para adicionar o mtodo stream na interface sem quebrar as implementaes existentes da Collection de todo mundo, o Java adicionou o stream como um mtodo da
interface, fornecendo uma implementao padro:
interface Collection<E> {
default Stream<E> stream() {
return StreamSupport.stream(spliterator());
}
}

Ento, agora temos a opo de implementar o mtodo stream ou se preferir usar a implementao padro fornecida pelo Java.

to, possvel criar um stream de, digamos, nmeros


aleatrios e no precisa mais ter um limite. aqui que,
algumas vezes, as coisas ficam um pouco confusas. Reflita sobre a seguinte questo: - Se tenho um stream
sempre. Como fao para parar o que estou fazendo
com os dados?
A resposta que potencialmente no ser finalizado. possvel fazer facilmente um trecho de cdigo
usando streams que continua para sempre, como se
fosse um loop while(true); infinito. Ele como um
Stream: se usar um Stream infinito, ele pode nunca
terminar. Mas tambm possvel fazer um Stream
parar - digamos, para fornecer um Stream infinito de
nmeros aleatrios, mas com um ponto de parada.
Assim o Stream vai parar e o programa pode continuar sua execuo.
O Stream fornece um pipeline (sequncia) de dados com trs componentes importantes:
1. Uma fonte de dados;
2. Zero ou mais operaes intermediarias, fornecendo um pipeline de Streams;
3. Uma operao terminal(final) que pode realizar
duas funes: criar um resultado ou um efeito colateral. (Um efeito colateral significa que talvez no
consiga retornar um resultado, mas ao invs disso,
consiga imprimir o valor.)

eMag | Java: Presente e Futuro 25

Nesse exemplo, iniciamos com uma Collection de


transaes e queremos determinar o preo total de
todas as transaes que foram realizadas por compradores de Londres. Obtemos um stream a partir da
Collection de transaes.
Depois obtemos um stream a partir da Collection
de transaes. Ento, aplicamos uma operao de filtro para produzir um novo Stream com os compradores de Londres.
A seguir, aplicamos a operao intermediaria
mapToInt para extrair os preos. E finalmente, aplicamos a operao final de soma para obter o resultado.
Do ponto de vista da execuo, o que aconteceu
aqui que o filtro e o mtodo de map (a operao
intermediaria) no realizaram um trabalho computacional. Foram apenas responsveis por configurar
o conjunto das operaes, e a computao real executada posteriormente, postergado at chamar a operao final nesse caso a soma (sum) que faz todo
trabalho acontecer.

em 1 (IntRange.rangeClosed(1, 10) gera um stream de 1 a 10);


Files.walk() passando um caminho e algum
parmetro de controle opcional que retorna um
stream de arquivos individuais ou subdiretrios;
Implementar a interface java.util.Spliterator
para definir sua prpria maneira de criar um
Stream. Para mais informaes sobre o Spliterator consulte o Javadoc do SE 8 fornecido pela
Oracle.

Operaes de finalizao de Stream


Depois de encadearmos todos esses streams, podemos especificar uma operao de finalizao para
executar as pipeline e todas as operaes (sequencialmente ou em paralelo) e produzir os resultados finais
(ou efeitos colaterais).
int sum = transactions.stream().
filter(t -> t.getBuyer().getCity().equals(London)). //Lazy

Fontes de stream
H diversas formas de obter um Stream. Muitos
mtodos esto sendo adicionados a API de Collection
(usando a extenso de mtodos nas interfaces).
Atravs de uma List, Set, ou Map.Entry possvel
chamar um mtodo de Stream que retorna uma Stream com o contedo da coleo.
Um exemplo o mtodo stream(), ou parallelStream(), que internamente a biblioteca usa o framework
de fork/join para decompor as aes em diversas subtarefas.
H outras maneiras de obter um stream:
Fornecer um array para o mtodo stream() da
classe Arrays;
Chamar o mtodo Stream.of(), um mtodo esttico da classe Stream;
Chamar um dos novos mtodos estticos para
retornar um stream em particular, por exemplo:
IntStream.range(), fornecendo um ndice de
inicio e fim. Por exemplo, IntStream.range(1, 10)
gera um stream de 1 a 9 com incremento de 1

26 InfoQ Brasil

mapToInt(Transaction::getPrice). //Lazy
sum(); //Executa o pipeline

Inteface Iterable
Essa uma velha conhecida dos dias do Java 1.5, exceto que agora tem um mtodo forEach() que aceita
um Consumer, que aceita um simples argumento e
no retorna valor e produz um efeito colateral. Mas
continua sendo uma interao externa e a melhor forma de obter um lambda o mtodo map().

Exemplos:
Ritter conclui a apresentao com alguns exemplos
uteis, que esto listados a seguir com comentrios explicativos. (As linhas em negrito indicam o especial
uso demonstrado em cada exemplo).

Exemplo 1. Converter palavras para maisculo:

mapToInt(String::length).

List<String> output = wordList.stream().

// cria um novo stream com o tamanho das strings mapeando

// Mapa de toda a lista de String em maisculo.

// a atual String ao tamanho correspondente.

map(String::toUpperCase).

max().

// Converte o stream para uma lista.

// Coleta o maior elemento do stream de tamanho (como

collect(Collectors.toList());

uma optionalInt)
getAsInt();

Exemplo 2. Procurar as palavras

// Atualiza o OptionalInt com um int.

com tamanho par na lista:


stream().

Exemplo 6. Coleo de todas as palavras do arquivo


em uma lista:

//Seleciona somente as palavras com tamanho par.

List<String> output = reader.

filter(w -> (w.length() & 1 == 0).

lines().

collect(Collectors.toList());

flatMap(line -> Stream.of(line.split(REGEXP))).

List<String> output = wordList.

// Recebe um stream de palavras de

Exemplo 3. Contar as linhas de um arquivo:

// todas as linhas.

long count = bufferedReader.

filter(word -> word.length() > 0).

// Recebe um stream com linhas individuais.

// Filtra as Strings vazias.

Esse o novo mtodo do

collect(Collectors.toList());

// bufferedReader que retorna um stream<string>.

// Cria a lista de retorno.

lines().
// Conta os elementos do stream de entrada.
count();

Exemplo 7. Retorna a lista de palavras


minscula em ordem alfabtica:
List<String> output = reader.lines().

Exemplo 4. Juntar as linhas 3 e 4 em uma nica String:

flatMap(line -> Stream.of(line.split(REGEXP))).

String output = bufferedReader.

filter(word -> word.length() > 0).

lines().

map(String::toLowerCase).

// Pula as duas primeiras linhas.

// Atualiza o Stream da fonte com o Stream de

skip(2).

// letras minsculas.

// limita a stream a apenas as prximas duas linhas.

sorted().

limit(2).

// Atualiza o stream com a verso ordenada.

// Concatena as linhas.

collect(Collectors.toList());

collect(Collectors.joining());

// Cria e retorna uma Lista

Exemplo 5. Encotrar o tamanho da linha mais longa


em um arquivo:
int longest = reader.lines().

eMag | Java: Presente e Futuro 27

Concluso
Simon Ritter conclui a apresentao declarando:
O Java precisa das expresses lambda para facilitar a vida do desenvolvedor. As expresses lambdas eram necessrias para a criao dos Streams e tambm para implementar a ideia de passagem de comportamento como a
passagem de valor. Tambm precisvamos ampliar as interfaces existentes, com o uso das extenses de mtodos do
Java SE 8, e que resolve o problema da retro compatibilidade. Isso permite fornecer a ideia de operaes em lote na
Collections e permite fazer coisas que so mais simples, e de um modo mais legvel. O Java SE 8 est basicamente
evoluindo a linguagem; evoluindo as bibliotecas de classes e tambm as maquinas virtuais ao mesmo tempo.
O Java 8 est disponvel para download e h um bom suporte a lambda em todos as principais IDEs. Sugiro
que todos os desenvolvedores Java faam o download e usem o Projeto Lambda.

Sobre o Autor
Simon Ritter o diretor do Evangelismo da tecnologia Java na
Oracle Corporation. Ritter trabalha com negcios de TI desde 1984
e bacharel de Cincia graduado em Fsica pela universidade de
Brunel no Reino Unido.

28 InfoQ Brasil

QUO FUNCIONAL O JAVA 8?

por Ben Evans, traduzido por Roberto Pepato

Tem sido falado que o Java 8 trouxe a Programao Funcional para o Java. Neste artigo, Ben Evans discute o que significa ser funcional. Olhando
a evoluo do Java em particular o seu sistema de tipos, possvel ver como os novos recursos do Java 8, especialmente as expresses lambda,
mudam o panorama e fornecem alguns benefcios fundamentais para o estilo de programao funcional.

em-se falado muito sobre como


o Java 8 trouxe a Programao
Funcional para o Java - mas, o
que isso realmente quer dizer?
Neste artigo, ser apresentado o
que significa ser funcional para uma
linguagem, ou para um estilo de
programao. Olhando a evoluo
de Java, em particular o seu sistema
de tipos (type system), possvel ver
como os novos recursos do Java 8,
especialmente as expresses lambda, mudam este cenrio e oferecem
alguns dos principais benefcios da
programao funcional.

O que uma linguagem de


programao funcional?
Em sua essncia, uma linguagem
de programao funcional aquela
que trata da mesma forma tanto o cdigo como os dados. Isto significa que
uma funo deve ser um valor de primeira classe na linguagem e deve poder ser atribuda a variveis, passada
como parmetro para funes, entre
outras funcionalidades.
De fato, muitas linguagens funcionais vo ainda mais longe que isso
e enxergam a computao e os algo-

ritmos como estruturas mais fundamentais que os dados que operam.


Algumas destas linguagens buscam
desmembrar o estado do programa de
suas funes (de uma forma que parece contrria ao desejo das linguagens
orientadas a objetos, que normalmente buscam manter algoritmos e dados
integrados).
Um exemplo seria a linguagem de
programao Clojure. Apesar de executar sobre a Java Virtual Machine,
que baseada em classes, a Clojure
fundamentalmente uma linguagem
funcional e no expe diretamente as

eMag | Java: Presente e Futuro 29

classes e objetos na linguagem de alto


nvel (embora exista uma boa interoperabilidade com Java).
Uma funo Clojure, como a funo de processamento de log apresentada a seguir, um cidado de
primeira classe na linguagem e no
precisa ser declarada em uma classe
para existir.

utilizao de estruturas de dados mutveis.


No entanto, existem outras linguagens onde comum escrever programas no estilo funcional, apesar da
linguagem no impor esta restrio.
Um exemplo seria o Scala, que uma
mistura de linguagens orientadas a
objetos e funcional e permite utilizar
funes como valores, tais como:

(defn build-map-http-entries [log-file]


(group-by :uri

val sqFn = (x: Int) => x * x

(scan-log-for-http-entries log-file)))

A programao funcional til


quando os programas so escritos em
termos de funes que sempre retornam a mesma sada para uma entrada
especfica (independente de qualquer
outro estado presente no programa
em execuo) e que no causem efeitos colaterais ou alterem quaisquer
estados do sistema. Funes que obedecem a esta restrio as vezes so
chamadas de funes puras e se
comportam da mesma forma que as
funes matemticas.
A grande vantagem das funes
puras que so mais fceis de entender, pois seu funcionamento no depende de estado externo. As funes
podem ser facilmente combinadas
entre si e isto pode ser observado
em estilos de fluxos de trabalho dos
desenvolvedores como no estilo Ler,
Executar, Imprimir e Lao (Read, Execute, Print, Loop - REPL), comum a
dialetos Lisp e outras linguagens com
forte herana funcional.

Programao funcional em
linguagens no funcionais
A caracterstica de uma linguagem ser ou no funcional no uma
condio binria ao invs disto, as
linguagens existem em um espectro.
Em um dos extremos desta espectro
esto as linguagens que basicamente
foram a programao funcional, frequentemente proibindo estruturas de
dados mutveis. Clojure um exemplo de linguagem que no permite a

30 InfoQ Brasil

Mantendo a sintaxe de classes e


objetos que muito prximas do Java.
No outro extremo, possvel escrever programas utilizando programao funcional em linguagens completamente no-funcionais, como o
caso do C, desde que a disciplina de
programao adequada e as convenes sejam mantidas.
Com isto em mente, a programao
funcional deve ser vista como uma
funo de dois fatores um que
relevante para as linguagens de programao e outro que relevante para
programas escritos nesta linguagem:
1) At que ponto a linguagem de
programao utilizada auxilia ou refora a programao funcional?
2) Como este programa especfico
faz uso das caractersticas funcionais
fornecidas pela linguagem? Ele evita
utilizar recursos no-funcionais, tais
como estado mutvel?

Java - um pouco de histria


Java uma linguagem com personalidade, otimizada para facilitar a
legibilidade, a acessibilidade aos programadores iniciantes e para promover o suporte e a estabilidade a longo
prazo. Estas decises de design tm
um custo, como exemplo a verbosidade e no sistema de tipos que pode as
vezes parecer inflexvel quando comparado a outras linguagens.
No entanto, o sistema de tipos de
Java evoluiu, ainda que de forma relativamente lenta, ao longo da histria
da linguagem. Vamos dar uma olhada

em algumas formas que a linguagem


assumiu ao longo dos anos:

O sistema de tipos original


do Java

O sistema de tipos original do Java


j possui mais de 15 anos. simples e
claro, pois os tipos so de referncia
ou primitivos. Os tipos de referncias
(Reference Types) so classes, interfaces ou arrays (vetores).
As classes so a essncia da plataforma Java uma classe a unidade bsica de funcionalidade que a
plataforma Java vai carregar ou referenciar e todo o cdigo destinado
para execuo deve residir em uma
classe;
As interfaces no podem ser diretamente instanciadas, ao invs disso, uma classe que implementa a API
definida pela interface deve ser construda;
Os arrays podem armazenar tanto tipos primitivos como instncias de
classes, ou outros arrays;
Todos os tipos primitivos so
definidos pela plataforma e o programador no pode definir novos tipos
primitivos.
Desde seus primeiros dias, o sistema de tipos do Java vem insistindo
em um ponto muito importante, o de
que cada tipo deve possuir um nome
pelo qual possa ser referenciado. Esta
idia conhecida como tipagem nominativa (nominative typing) e o Java
uma linguagem com forte tipagem
nominativa.
Mesmo as chamadas classes annimas internas (anonymous inner
classes) possuem um tipo pelo qual
o programador deve referenci-las
o tipo da interface que implementam:
Runnable r = new Runnable()
{ public void run()
{ System.out.println(Hello World!); } };\

Outra forma de se dizer isto a de


que cada valor no Java um tipo primitivo ou a instncia de alguma classe.

Alternativas a tipos nomeados


Outras linguagens no tm esse
fascnio por tipos nomeados. O Java
no tem um conceito equivalente ao
do Scala de um tipo que implementa
um mtodo especfico (de uma assinatura especfica). No Scala, isto poderia
ser escrito da seguinte forma:
x : {def bar : String}

Lembre-se que no Scala indica-se o


tipo da varivel direita (aps o : ),
ento, isto lido como: x de um tipo
que possui um mtodo chamado bar
que retorna uma String. Podemos
utilizar esta informao para definir
um mtodo no Scala da seguinte forma:
def showRefine(x : {def bar : String})
= { print(x.bar) }

e ento, possvel definir um objeto


Scala desta forma:
object barBell { def bar = Bell }

e ao chamar o mtodo
showRefine(barBell), o esperado ser:
showRefine(barBell) Bell

Este um exemplo de tipagem por


refinamento. Os programadores que
vm de linguagens dinmicas podem
estar familiarizados com o conceito
de duck typing (se ele anda como um
pato e grasna como um pato, ento
um pato). Tipagem por refinamento estrutural (Structural refinement
typing) um conceito similar, exceto
que duck typing trata de tipos em tempo de execuo, enquanto os tipos de
refinamento estrutural funcionam em
tempo de compilao.
Em linguagens que possuem a tipagem por refinamento estrutural de
forma completa, estes tipos refinados
podem ser utilizados em qualquer
lugar que o programador possa esperar - como o tipo de parmetro de

um mtodo. Em contraste, o Java no


possui esta categoria de tipagem (desconsiderando alguns casos extremos
e bizarros).

O sistema de tipos do Java 5


O lanamento do Java 5 trouxe trs
principais novos recursos ao sistema
de tipos - tipos enumerados (enums),
anotaes (annotations) e tipos genricos (generic types).
Os tipos enumerados (enums)
so similares a classes em alguns aspectos, mas eles tm a propriedade
de restringir o nmero de instncias
existentes, e cada instncia distinta
e especificada na descrio da classe.
Planejado originalmente para utilizao como constante de tipo seguro
(typesafe constant), ao invs da prtica ento comum de usar nmeros
inteiros para constantes, a construo
enum tambm permite padres adicionais que so, por vezes, extremamente teis;
As anotaes (annotations) esto
relacionadas a interfaces a palavra
reservada para declarar uma @interface com o @ inicial indicando que
este um tipo de anotao. Como o
nome sugere, elas so utilizadas para
anotar elementos de cdigo Java com
informaes adicionais que no afetam seu comportamento. Anteriormente, o Java utilizava o conceito de
interfaces de marcao para fornecer uma forma limitada deste tipo de
metadado, mas as anotaes so consideravelmente mais flexveis;
Os tipos genricos (generic
types) do Java fornecem tipos parametrizados - a ideia de que um tipo
pode funcionar como um recipiente
para objetos de outro tipo, sem levar
em conta as especificidades de exatamente qual o tipo que est sendo
contido. O tipo que se encaixa no recipiente frequentemente chamado de
tipo de parmetro (parameter type).
Dos recursos introduzidos no Java
5, os enums e as anotaes oferecem
novas formas de tipos de referncia

que exigem tratamento especial pelo


compilador e que so efetivamente
separados das hierarquias de tipos
existentes.
Os tipos genricos adicionam uma
complexidade significativa ao sistema
de tipos do Java muito em razo do
fato de serem um recurso puramente
de tempo de compilao. Isto exige
que o desenvolvedor Java esteja atento aos sistemas de tipo em tempo de
compilao e em tempo de execuo,
que so ligeiramente diferentes entre
si.
Apesar dessas mudanas, a insistncia do Java em tipos nominativos
permaneceu. Os nomes de tipo agora incluem List<String> (lido como:
Lista de String) e Map<Class<?>,
CachedObject> (Map de Classe de
Tipo Desconhecido para CachedObject), mas estes ainda so tipos nomeados, e cada valor no primitivo
ainda uma instncia de uma classe.

Recursos introduzidos
no Java 6 e 7
O Java 6 foi essencialmente uma
verso para melhoria de desempenho
e de bibliotecas. As nicas mudanas
para o sistema de tipos foi a expanso
do papel das anotaes e o lanamento da capacidade de processamento
de anotao conectvel (pluggable).
Isto no impactou a maioria dos desenvolvedores Java e no disponibilizou um sistema de tipos conectveis
(pluggable type system) no Java 6.
O Java 7 no mudou materialmente
o sistema de tipos. Os nicos novos
recursos, todos de baixa relevncia,
so:
Pequenas melhorias na inferncia de tipos do compilador javac;
Tratamento de assinatura polimrfica - utilizado como um detalhe
de implementao para o recurso chamado method handles - que, por sua
vez, foi utilizado para implementar
expresses lambda no Java 8;
O Multi-catch fornece algumas
caractersitcas de tipos de dados al-

eMag | Java: Presente e Futuro 31

gbricos (algebraic data types) - mas


so puramente internos ao javac e no
apresentam nenhuma consequncia
real para o programador usurio final.

O sistema de tipos do Java 8


Ao longo de sua histria o Java foi
essencialmente definido por seu sistema de tipos. Ele fundamental para a
linguagem e tem mantido estrita aderncia aos tipos nominativos. De um
ponto de vista prtico, o sistema de
tipos do Java no mudou muito entre
o Java 5 e Java 7.
A primeira vista, poderamos esperar que o Java 8 mudasse isso. Afinal de contas, uma expresso lambda
parece nos afastar da tipagem nominativa:
() -> { System.out.println
(Hello World!); }

Este um mtodo, sem um nome,


que no recebe parmetros e retorna
void. Ainda perfeitamente tipado de
forma esttica, mas agora annimo.
Ser que escapamos do Reino dos
Substantivos? Isto realmente uma
nova forma de tipos para o Java?
A resposta , talvez infelizmente,
no. A JVM, na qual o Java e outras
linguagens executam, estritamente
associada ao conceito de classes. O
carregamento de classes (classloading) fundamental para os modos
de segurana e verificao da plataforma Java. Simplificando, seria muito, muito difcil conceber um tipo que
no fosse, de alguma forma, representado atravs de uma classe.
Ao invs de criar uma nova categoria de tipos, as expresses lambda
do Java 8 so automaticamente convertidas pelo compilador para uma
instncia de uma classe. A classe em
questo determinada por inferncia
de tipos. Por exemplo:
Runnable r = () -> { System.out.println
(Hello World!); };

32 InfoQ Brasil

A lambda expression do lado direito um valor perfeitamente vlido


no Java 8 - mas seu tipo inferido do
valor esquerda - portanto, ela na
verdade um valor do tipo Runnable.
Entretanto, note que se uma expresso lamdba for utilizada de forma
incorreta, ocorrer um erro de compilao. A tipagem nominativa ainda a
forma utilizada pelo Java e at mesmo
a introduo de lambdas no mudou
isso.

Quo funcional o Java 8?


Finalmente, vamos voltar para
questo que fizemos no incio do artigo Quo funcional o Java 8?
Antes do Java 8, se o desenvolvedor
quisesse escrever no estilo funcional,
seria necessrio utilizar tipos aninhados (geralmente classes internas
annimas) como um substituto para
literais de funes (function literals).
As colees de bibliotecas padro no
ajudariam muito o cdigo e a maldio da mutabilidade estaria sempre
presente.
As expresses lambda do Java 8
no transformam de forma mgica o
Java em uma linguagem funcional.
Em vez disso, seu efeito o de criar
uma linguagem ainda imperativa,
com sistema de tipos ainda nominativos e que possui um maior suporte
s expresses lambda como literais
de funes. Simultaneamente, as melhorias para as colees de bibliotecas
permitiram que os desenvolvedores
Java comeassem a adotar expresses
funcionais simples (como filter e map)
para tratar cdigo que seria de alta
complexidade sem estes recursos.
O Java 8 demandou a introduo
de alguns novos tipos para representar os blocos de construo bsicos de
fluxos de execuo (pipelines) funcionais interfaces como Predicate,
Function e Consumer no pacote java.
util.function. Estas adies tornaram
o Java 8 capaz de permitir programao ligeiramente funcional mas
sua necessidade de represent-los

como tipos (e sua localizao no pacote utilitrio, ao invs do core da


linguagem) demonstra o estrangulamento que a tipagem nominativa
impe linguagem Java e o quo distante a linguagem est da pureza de
dialetos Lisp ou de outras linguagens
funcionais.
Apesar de tudo o que foi exposto
at aqui, este pequeno subconjunto
do poder das linguagens funcionais
pode muito bem ser tudo que a maioria dos desenvolvedores realmente
precisa para suas atividades dirias
de desenvolvimento. Para usurios
avanados, outras linguagens (na
JVM e em outros lugares) ainda existem e, sem dvida, continuam a prosperar.

JAVA 7 - CARACTERSTICAS QUE


VIABILIZAM
O
JAVA
8
por Ben Evans, traduzido por Diogo Carleto
Neste artigo, Ben Evans explora algumas funcionalidades do Java 7 que preparam o terreno para os novos recursos do Java 8.

uma verdade da indstria de


tecnologia que os desenvolvedores no podem ser mais felizes do que quando h cerveja ou uma
oportunidade de reclamar sobre algo
oferecido.
Ento, mesmo aps os esforos de
Mark Reinhold e a equipe Java para
envolver a comunidade no roadmap
aps a aquisio da Oracle (a deciso
Plano A / Plano B), muitos desenvolvedores Java sentiram que o Java 7
no era bem um release.
Neste artigo, tentamos refutar essa
tese, explorando as funcionalidades
do Java 7 que preparam o terreno para
as novas funcionalidades do Java 8.

Operador Diamante
O Java muitas vezes criticado por
ser excessivamente verboso. Uma das
reas mais comuns desta queixa est
na atribuio. No Java 6, somos forados a escrever declaraes de atribuio como esta:

Na verdade, linguagens como Scala fazem uma grande quantidade de


inferncia de tipos a partir de expresses e, de fato, declaraes de atribuio podem ser escritas to simples
quanto isso:
val m = Map(x ->

Map<String, String>

24, y -> 25, z -> 26);

m = new HashMap<String, String>();

Esta declarao possui muita informao redundante - devemos ser


capazes, de alguma forma, de fazer o
compilador entender mais sobre isso
sozinho, e no exigir que o programador seja to explcito.

A palavra-chave val indica que


a varivel no pode ser reatribuda
(como a palavra-chave final para variveis Java). Nenhum tipo de informao especificado sobre a varivel,
ao invs disso o compilador Scala examina o lado direito da declarao de

eMag | Java: Presente e Futuro 33

atribuio e determina o tipo correto


para a varivel observando que valor
est sendo atribudo.
No Java 7, foram introduzidos alguns recursos de tipo de inferncia limitados, e declaraes de atribuies
podem agora ser escritas da seguinte
forma:
Map<String, String> m = new HashMap<>();

As principais diferenas entre essa


forma e a do Scala, que no Scala os
valores tm tipos explcitos e esses
so os tipos de variveis inferidos. No
Java 7, o tipos das variveis so explcitos e o tipo de informao sobre esses valores que inferido.
Alguns desenvolvedores se queixaram de que eles prefeririam a soluo Scala, mas acaba por ser menos
conveniente no contexto de uma das
principais caractersticas do Java 8 expresses lambda.
No Java 8, podemos escrever uma
funo que adiciona 2 a um inteiro
dessa maneira:

escolhemos essa sintaxe por ser muito


similar ao equivalente em Scala e permitir que os desenvolvedores vejam
as similaridades mais facilmente.
Ao especificar explicitamente o
tipo de fn como uma Function que recebe um argumento Integer e retorna
outro Integer, o compilador Java tem
condies de inferir o tipo do parmetro x como Integer. Este o mesmo padro que vimos na sintaxe diamante
no Java 7 - especificamos os tipos de
variveis e inferimos o tipo de valores.
Vamos olhar a expresso lambda
correspondente no Scala:
val fn = (x : Int) => x + 2;

Aqui temos que especificar explicitamente o tipo do parmetro x. Como


no temos o tipo preciso de fn, ento
no temos nada para inferir. A forma
de ler no Scala no extremamente
difcil, mas a forma do Java 8 tem uma
certa clareza na sintaxe que lembra a
sintaxe diamante do Java 7.

Function<Integer, Integer> fn = x -> x + 2;

Manipulador de Mtodos

A interface Function nova no Java


8 e est no pacote java.util.function,
juntamente com formas especializadas para tipos primitivos. Entretanto,

Os manipuladores de mtodos so
simultaneamente o novo recurso mais
importante do Java 7 e o que menos
provvel de ser usado no dia-a-dia da

maioria dos desenvolvedores Java.


Um manipulador de mtodo uma
referncia tipada de um mtodo para
execuo. Podem ser considerados
como ponteiros para funo segura
(para desenvolvedores familiarizados
com o C/C++) ou como A base do Reflection reimaginado pelos desenvolvedores modernos Java.
Os manipuladores de mtodos desempenham um papel enorme na implementao de expresses lambda.
Prottipos anteriores do Java 8 tinham
cada expresso lambda convertidas
em uma classe interna annima em
tempo de compilao.
Vamos comear lembrando que a
expresso (ao menos no Java) lambda
composta por uma assinatura de funo (que na API de manipuladores de
mtodo ser representado pelo objeto
MethodType) e um corpo, mas no necessariamente um nome de funo.
Isto sugere que poderamos converter a expresso lambda em um
mtodo sinttico que tem a assinatura
correta e que contm o corpo do lambda. Por exemplo a funo:
Function<Integer, Integer> fn = x -> x + 2;

convertido pelo compilador do Java 8


no mtodo privado com esse bytecode:

private static java.lang.Integer lambda$0(java.lang.Integer);


descriptor: (Ljava/lang/Integer;)Ljava/lang/Integer;
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokevirtual #13 // Mtodo java/lang/Integer.intValue:()I
4: iconst_2
5: iadd
6: invokestatic #8 // Mtodo java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: areturn

Esse mtodo tem a assinatura e


semntica correta (recebe um Integer
e retorna um Integer). Para usar essa

34 InfoQ Brasil

expresso lambda, precisamos de um


manipulador de mtodo referenciando-a, que ser usado para construir

um objeto com o tipo apropriado,


como veremos na prxima funcionalidade que iremos discutir.

invokedynamic
A ltima funcionalidade do Java 7
que abre as portas para o Java 8 ainda mais esotrica que os manipuladores de mtodo. Esse o novo bytecode
invokedynamic - o primeiro bytecode
a ser adicionado plataforma desde o
Java 1.0. Esta funcionalidade quase
impossvel de ser usada por desenvolvedores na verso 7, porque nessa
verso o javac no ir, sob nenhuma
circunstncia, gerar um arquivo class
que contenha isso.
Em vez disso, o bytecode foi projetado ser usado por desenvolvedores
de outras linguagens alm do Java, tal
como JRuby, que requer muito mais
execuo dinmica que o Java. Para
ver como o invokedynamic funciona,
discutiremos como as chamadas de
mtodo Java so compiladas em bytecode.
Uma chamada padro de mtodo
Java ser convertida em um pedao
de bytecode da JVM, que frequentemente referenciado como uma chamada local. Esta chamada composta
de um cdigo de operao de envio
(tal como invokevirtual, para chamadas de mtodo de instncia normal)
e uma constante (um deslocamento
para o Constant Pool da classe) que
indica qual o mtodo a ser chamado.
Os diferentes cdigos de invocao
tm regras diferentes que definem
como a pesquisa de mtodo feita,
mas at Java 7 sempre eram utilizadas
constantes para saber diretamente
qual o mtodo a ser chamado.
O invokedynamic diferente. Ao
invs de fornecer uma constante que
indica diretamente qual mtodo deve
ser chamado, o invokedynamic fornece um mecanismo de indireo que
permite o cdigo do usurio decidir
qual mtodo chamar em tempo de
execuo.
Quando a primeira chamada com
invokedynamic encontrada, o alvo
ainda no conhecido. Ao invs disso, um manipulador de mtodo (chamado mtodo inicial) invocado.

Esse mtodo inicial retorna um objeto


CallSite, que contm outro manipulador de mtodo, que o alvo atual da
chamada do invokedynamic.
1) A chamada do invokedynamic
encontrada no fluxo de execuo (inicialmente desvinculado); 2) Chama
o mtodo inicial e retorna um objeto
CallSite; 3) O objeto CallSite tem um
manipulador de mtodo (o alvo); 4) Invoca o mtodo manipulador alvo.
O mtodo inicial a maneira na
qual o cdigo do usurio escolhe qual
mtodo precisa ser chamado. Para expresses lambda, a plataforma utiliza
um mtodo de inicializao fornecido
pela biblioteca, chamado de lambda
meta-factory.
Este tem argumentos estticos que
contm um manipulador para o mtodo sintetizado (veja ltima seo) e a
assinatura correta para o lambda.
O meta-factory retorna um CallSite
que contm um manipulador de mtodo e que, por sua vez, retorna uma
instncia do tipo correto que a expresso lambda foi convertida. Logo, uma

declarao como:
Function<Integer, Integer> fn = x -> x + 2;

convertida para uma chamada invokedynamic assim:


Code:
stack=4, locals=2, args_size=1
0: invokedynamic #2, 0 // InvokeDynamic
#0:apply:()Ljava/util/function/Function;
5: astore_1t

O mtodo de inicializao do invokedynamic o mtodo esttico


LambdaMetafactory.metafactory(),
que retorna um objeto CallSite ligado
ao manipulador de mtodo alvo, que
retornar um objeto que implementa
a interface Function.
Quando uma instruo invokedynamic termina, um objeto que implementa Function e que tenha uma
expresso lambda como contedo do
mtodo apply() colocado no topo da
fila, e o resto do cdigo pode seguir
normalmente.

Concluso
Obter expresses lambda na plataforma Java sempre foi e vai ser uma tarefa
desafiadora, mas garantindo que o terreno adequado estava no lugar, o Java 7
facilitou consideravelmente esse esforo. O plano B no s forneceu aos desenvolvedores o lanamento antecipado do Java 7, mas tambm permitiu que as
principais tecnologias realizassem testes em produo antes de usarem o Java 8
e especialmente expresses lambda.

Sobre o Autor
Ben Evans o CEO da jClarity, uma startup que fornece ferramentas de
desempenho para auxiliar equipes de desenvolvimento e ops. Ele um organizador no LJC (JUG Londres) e membro do comit executivo do JCP, ajudando a definir padres para os ecossistemas Java. Ele um Java Champion; JavaOne Rockstar; coautor do The Well-Grounded Java Developer
e um palestrante pblico na plataforma Java, desempenho, concorrncia
e tpicos relatados.

eMag | Java: Presente e Futuro 35

Q&A:
NOVIDADES
DO
JAVA
8
por Matt Raible, traduo de Diogo Carleto
O Java 8 uma das atualizaes de linguagem de programao mais esperadas dos ltimos anos. O novo release contm a API de datas, API de
stream e os lambdas, remove o permgen e traz um longo conjunto de melhorias. Para aprender mais sobre este lanamento, conversamos com
Georges Saab, vice-presidente de desenvolvimento de software do Java Platform Group na Oracle.
InfoQ: Para os que no tm seguido o projeto Lambda de perto, poderia
nos dar uma ideia do que foi envolvido nesta implementao? Talvez seja
a primeira vez que tanto a linguagem
como a VM e as bibliotecas evoluram
juntas de maneira coordenada.
A maioria das grandes funcionalidades
em verses anteriores foi feita de maneira que somente uma dessas trs reas foi
afetada; ou as mudanas em cada rea foram introduzidas ao longo de uma srie de
grandes releases. Com o projeto Lambda
no Java 8, fizemos um mudanas coordenadas, envolvendo a linguagem, as bibliotecas e a JVM. Ao longo do desenvolvimento,
cada rea influenciou e fortaleceu o design
e a implementao das demais.
Experimentamos, por exemplo, com implementaes alternativas do Lambda na
JVM e descobrimos que poderamos utilizar o InvokeDynamic. Ao faz-lo, encontramos pontos que poderiam ser melhorados
no prprio InvokeDynamic. O desejo de
utilizar Lambdas de forma natural com as
Collections nos levou ao design da Streams
API e depois aos mtodos de extenso os
quais exigiram suporte da linguagem.
Tem sido um processo evolutivo ao longo de vrios anos, com bastante feedback
da comunidade.

InfoQ: Voc acredita que a adio


de lambdas ir trazer de volta ao Java
os desenvolvedores Groovy e Scala?
importante lembrar que essas duas
linguagens (e muitas outras) executam na
JVM. Trabalhamos muito para suportar
outras linguagens alm do Java na plataforma, e sinto que h muito que os implementadores de linguagens podem aprender com essas experincias. claro que

36 InfoQ Brasil

muito mais fcil experimentar com uma


linguagem com poucos milhares de desenvolvedores que com muitos milhes. Nosso
enfoque tem sido em abordar os aspectos
que melhoram a vida dos milhes de programadores Java, evoluindo a plataforma e
a linguagem de forma consciente e responsvel.

InfoQ: A combinao do Lambda


e da Streams API ajuda a desenvolver
cdigo limpo e conciso, mas foram
levantadas preocupaes quanto ao
impacto no desempenho, na medida
que filtros so aplicados seguidamente para reduzir conjuntos de maneira
funcional. Quais otimizaes foram
introduzidas para reduzir esse impacto?
As Streams permitem operaes intermedirias e terminais. As operaes intermedirias, como filtragem, no executam
nenhuma filtragem em si; criam um novo
Stream, que quando percorrido, fornece os
elementos que correspondem a um dado
predicado.
Dessa forma, por um lado, a criao de
filtros adicionais poderia resultar em trabalho adicional em tempo de execuo; por
outro, o processamento de streams sob

demanda, assim como as operaes intermedirias de streams, permite ganhos de


eficincia importantes. Isso porque vrias
operaes podem ser realizadas em uma
nica passagem sobre os dados. E com otimizaes importantes da JVM nos bastidores possibilitado pelo design dos lambdas,
o impacto de filtros adicionais pode ser reduzido em boa parte.
Outro ponto a ser considerado que a
utilizao do paralelismo com Streams e
Lambdas foi simplificado. As operaes de
streams em paralelo podem se beneficiar
da diminuio das restries de ordenao,
em que os usurios no conhecem conflitos
de ordenao do stream subjacente.

InfoQ: Outra funcionalidade importante do Java 8 so as Annotations


nos tipos do Java, para permitir que
verificadores de tipos plugveis sejam desenvolvidos. Poderia nos falar
um pouco mais sobre isso?
Essa funcionalidade permite o uso de
anotaes nos nomes dos tipos, na maioria dos lugares onde estes tipos podem ser
usados. Como resultado da mudana, os
desenvolvedores podem agora escrever
anotaes para detectar condies de erros
em tempo de compilao, usando verifica-

dores de tipos plugveis. Esses verificadores e esquemas de anotaes esto sendo


desenvolvidos na comunidade para erros
de null-pointer, locking e internacionalizao.
Uma boa fonte de informao e implementao o Checker Framework do Prof.
Michael Ernst do checker-framework.org,
que inclui um checker para no-nulos, dentre mais de uma dzia dessas ferramentas.
Ernst tambm atuou como lder da co-spec
na JSR 308, no qual esta funcionalidade da
linguagem foi especificada.
Seria timo ver os resultados de pelo
menos um desses esquemas de anotaes
sendo aplicado sobre a base de cdigo da
JDK no futuro; e ver a comunidade mais
ampla de desenvolvedores Java comear
a utilizar esta tecnologia em suas prprias
bases de cdigo, alm de desenvolver novos verificadores para outros aspectos de
qualidade de software.
Especialmente com respeito a sistemas
embarcados e outros em que a segurana
seja crtica, esse tipo de inovao permitiria que propriedades cruciais e restries
de tipos e seu uso fossem qualificados e
analisado estatisticamente, como parte do
processo de compilao. um caminho
para usurios de outras linguagens nesse
domnio migrarem para a plataforma Java.

InfoQ: Para linguagens dinmicas, quais so as principais melhorias


no Java 8, em sua opinio?
So as melhorias de performance na
Mquina Virtual HotSpot em geral e no
invokedynamic em particular. Outra nova
funcionalidade significativa o engine JavaScript Nashorn. Melhorar o desempenho
do Nashorn nos ajudou a encontrar novas
oportunidades de otimizao da VM para
implementaes de linguagens dinmicas.
Alm disso, o Nashorn agora fornece
uma maneira conveniente de usar o Java a
partir do JavaScript, permitindo que aplicaes JavaFX inteiras sejam escritas em
JavaScript e executadas na JVM. Essa interoperabilidade transparente entre o Java e
linguagens dinmicas executando na JVM,
oferece uma maneira poderosa de se escrever aplicaes web.

InfoQ: Preocupaes com Java e


segurana tiveram muito destaque
nos ltimos tempos. O Java 8 traz melhorias nessa rea, no plug-in do Java
ou em partes relacionadas?
Uma srie de melhorias importantes de
segurana e novas funcionalidades foram
entregues como parte das atualizaes do
Java SE 7, incluindo Deployment Rule Sets
(uma funcionalidade para empresas que
gerenciam o seu ambiente de desktop Java
diretamente) e Exception Site Lists (lista de
sites de exceo). A segurana no Java
uma de nossas prioridades.
Alm disso, o Java SE 8 contm funcionalidades novas de segurana. As mais
perceptveis so as na implementao do
Transport Layer Security: TLS 1.2. Este
agora o padro na plataforma. Em termos
globais de APIs de segurana, existe uma
srie de outras melhorias, desde aperfeioamentos na verificao de revogao de
certificados, at o uso de novos algoritmos
de criptografia.

InfoQ: Voc sabe qual o percentual de desenvolvedores Java usando


Java 5, 6 e 7? Existe algum plano para
acelerar a adoo do Java 8?
Ao longo dos ltimos seis a nove meses,
tenho falado em conferncias ao redor do
mundo e toda vez pergunto qual verso
esto usando. Apoiado sobre essa pesquisa
informal e no cientfica, diria que a maior
parte dos desenvolvedores Java esto
usando o Java SE 7 hoje, com minoria (significativa) ainda usando na verso 6, e um
nmero pequeno em verses mais antigas.
Do ponto de vista do desenvolvedor, o
Java SE 8 tem muitas razes convincentes
para a rpida adoo, como os novos recursos da linguagem e APIs. E com IDEs como
NetBeans, Eclipse e IntelliJ IDEA trabalhando para oferecer suporte aos novos recursos, espero ver os desenvolvedores adotar
o Java 8 rapidamente.

InfoQ: Um dos principais temas


do JavaOne 2013 foi a unificao do
Java ME, SE e EE. At que ponto o Java
8 caminhou nessa direo?

Uma das muitas novas funcionalidades


no Java SE 8 o suporte a Compact Profiles
(perfis compactos), que definem subconjuntos de perfis da plataforma Java SE. Isso
permite que aplicaes que no requerem
toda a plataforma sejam publicadas e executadas em dispositivos com menor capacidade.
No mais, houve outras melhorias no
HotSpot, como a reduo do tamanho de
metadados de classes e o tamanho da VM
em geral. Com isso o JDK 8 pode ser escalado para o desenvolvimento de aplicativos
e a implantao em pequenos dispositivos.
E a nova ferramenta jdeps que vem com o
JDK 8 permite descobrir de qual Profile o
cdigo sua aplicao depende.
Vindo de outra direo, o Java ME 8 est
sendo aprimorado a se alinhar mais com o
Java SE 8, quando a linguagem, VM e bibliotecas. Ainda no possvel utilizar lambdas
em cdigo Java ME 8, mas a plataforma
agora suporta construes de linguagem
Java introduzidas no Java SE 1.5, 6 e 7, como
assertions, generics, enumerations, strings
em switches, declaraes try-with-resources e o operador diamond.
Da mesma forma, as classes das bibliotecas do ncleo do Java foram atualizadas
com suporte para protocolos web modernos, como IPv6 e funcionalidades avanadas de segurana, incluindo o suporte para
TLS 1.2. Isso torna as plataformas Java SE e
Java ME mais prximas do que nunca.

InfoQ: Quando veremos a funcionalidade de Stripped Implementations adicionadas ao Java? (Stripped


Implementations permitem que uma
implementao especfica do Java SE
seja empacotada com a biblioteca Java
e o cdigo da aplicao. Elementos
desnecessrios so omitidos parcialmente ou por inteiro.)
Precisaremos voltar a examinar como a funcionalidade de Stripped Implementations pode
ser adicionada plataforma em uma verso anterior 9. No se trata de um problema tcnico,
mas sim de garantir que o texto de especificao e aspectos jurdicos permitam a utilizao
em vrios cenrios, ao mesmo tempo evitando
que haja fragmentao da plataforma Java.

eMag | Java: Presente e Futuro 37

DO
GROOVY
AO
JAVA
8
por Dan Woods, traduzido por Daniel Sousa
Este artigo focar nas semelhanas entre o Groovy e o Java 8, e vai demonstrar o quo familiar os conceitos do Groovy se traduzem para Java 8.

esenvolvedores Groovy tero mais facilidade


para adotar os conceitos e novas construes
da linguagem oferecida pelo Java 8. Muitas das
melhorias oferecidas na prxima verso do Java so
caractersticas que o Groovy oferece h anos. Desde
uma nova sintaxe at estilos de programao funcional,
lambdas, coleo de streams, e referncias de mtodos
como cidados de primeira classe. Os desenvolvedores
Groovy tero uma vantagem ao escrever o cdigo Java no
futuro. Este artigo focar nas semelhanas entre o Groovy
e o Java 8, e vai demonstrar o quo familiar os conceitos
do Groovy se traduzem para Java 8.
Comearemos discutindo estilos de programao,
como atualmente utilizamos a programao funcional no
Groovy, e de que forma as construes em Java 8 oferecem
um estilo de programao melhor.
Closures so, talvez, o melhor exemplo de programao
funcional em Groovy. Por baixo dos panos, uma closure
em Groovy apenas a implementao de uma interface
funcional. Uma interface funcional qualquer interface
que possua apenas um nico mtodo para implementar.
Por padro, as closures do Groovy so uma implementao
da interface funcional Callable, implementando o mtodo
call.

38 InfoQ Brasil

def closure = {
called
}
assert closure instanceof java.util.concurrent.Callable
assert closure() == called

Podemos fazer o Groovy implementar outras interfaces


funcionais por meio da converso de tipos closures.
public interface Function {
def apply();
}
def closure = {
applied
} as Function
assert closure instanceof Function
assert closure.apply() == applied

Closures e programao funcional se traduzem bem


em Java 8. Interfaces funcionais so muito importantes
na prxima verso do Java, pois o Java 8 oferece
implementao implcita de interfaces funcionais com a
introduo das funes Lambda.
As funes lambda podem ser pensadas, e utilizadas

como as closures em Groovy. Implementar uma interface


funcional em Java 8 oferece simplicidade semelhante a
das closures em Groovy.

return getAttribute(key);
}
default Map getScope() {
return scopeMap;

Callable callable = () -> called;


assert callable.call() == called;

}
}
static final WebFlowScope scope =

importante notar tambm que as funes lambda de


uma s linha oferecem retorno implcito, assim como no
Groovy.
No futuro, o Groovy tambm oferecer implementao
implcita de Interfaces Funcionais para as closures,
semelhante a oferecida pelo Java 8. Esta caracterstica
da as closures a capacidade de aproveitar as variveis
de instncia e mtodos sem derivar totalmente uma
subclasse concreta.

(Object key) -> edited_ + scope.getScope().get(key);


assert scope.put(attribute, val) == val;

No Java 8, mtodos default de interface podem tambm


ajudar-nos a implementar caractersticas do Groovy
como memoization e trampoline. Memoization pode ser
implementada simplesmente criando-se uma interface
funcional com um mtodo de interface default para
computar deterministicamente um resultado ou obter o
resultado do cache.

abstract class WebFlowScope {


private static final Map scopeMap = [:]

public interface MemoizedFunction<T, R> {

abstract def getAttribute(def name);

static final Map cache = new HashMap();

public def put(key, val) {

R calc(T t);

scopeMap[key] = val

public default R apply(T t) {

getAttribute(key)

if (!cache.containsKey(t)) {

cache.put(t, calc(t));

protected Map getScope() {

scopeMap

return (R)cache.get(t);

WebFlowScope closure = { name ->

static final MemoizedFunction<Integer, Integer> fib = (Integer n) -> {

edited_${scope[name]}

if (n == 0 || n == 1) return n;

return fib.apply(n - 1)+fib.apply(n-2);

assert closure instanceof WebFlowScope

};

assert closure.put(attribute, val) == edited_val

assert fib.apply(20) == 6765;

Em Java 8, as Interfaces Funcionais com mtodos


default na interface oferecem uma boa aproximao deste
conceito. Mtodos default em interfaces so algo novo
em Java. Eles foram concebidos para permitir melhorias
nas APIs principais do Java sem violar os contratos
de implementaes feitas em verses anteriores da
linguagem.
As funes lambda tambm tero acesso a mtodos
padro da interface em que so definidas. Isto significa
que APIs robustas podem ser construdas diretamente
em uma interface, dando recursos aos programadores
sem alterar a natureza do tipo ou do contrato no qual o
tipo pode ser utilizado.

De maneira similar, podemos utilizar mtodos default


de interface em Java 8 para desenvolver implementao
Trampoline. Trampoline uma estratgia de recurso
que no sobrecarrega a pilha de chamadas do Java, e
um recurso muito til do Groovy quando uma recurso
profunda necessria.
interface TrampolineFunction<T, R> {
R apply(T...obj);
public default Object trampoline(T...objs) {
Object result = apply(objs);
if (!(result instanceof TrampolineFunction)) {
return result;
} else {

public interface WebFlowScope {

return this;

static final Map scopeMap = new HashMap();

Object getAttribute(Object key);


default public Object put(Object key, Object val) {
scopeMap.put(key, val);

}
}
// Encapsula a chamada do TrampolineFunction para evitar um

eMag | Java: Presente e Futuro 39

operaes em cadeia em listas.

StackOverflowError
static

TrampolineFunction<Integer,

Object>

fibTrampoline

(Integer...objs) -> {

List<Integer> list = new ArrayList<>();


list.add(1); list.add(2);

Integer n = objs[0];

list.add(3); list.add(4);

Integer a = objs.length >= 2 ? objs[1] : 0;

List<Integer> newList =

Integer b = objs.length >= 3 ? objs[2] : 1;

list.stream().map((Integer n) -> n * 5).collect(Collectors.

if (n == 0) return a;

toList());

else return fibTrampoline.trampoline(n-1, b, a+b);

assert newList.get(0) == 5 && newList.get(1) ==

};

10 && newList.get(2) == 15 && newList.get(3) == 20;

Alm dos recursos bsicos das closures e dos recursos


mais avanados como Memoization e Trampolining,
alguns dos recursos mais prticos e teis que o Groovy
tem para oferecer esto relacionados s extenses da
linguagem para a API Collections. Em Groovy, podemos
utilizar estas extenses para escrever atalhos e realizar
operaes em listas usando o mtodo each.

O Groovy tambm oferece atalhos para filtrar listas


atravs do mtodo findAll.
def emails = [danielpwoods@gmail.com, nemnesic@gmail.com,
daniel.woods@objectpartners.com, nemnesic@nemnesic.com]
def gmails = emails.findAll { it.endsWith(@gmail.com) }
assert gmails = [danielpwoods@gmail.com, nemnesic@gmail.com]
De maneira semelhante, em Java 8 os desenvolvedores podem filtrar

def list = [1, 2, 3, 4]

uma lista utilizando a API Stream.

list.each { item ->

List<String> emails = new ArrayList<>();

println item
}

emails.add(danielpwoods@gmail.com);
emails.add(nemnesic@gmail.com);
emails.add(daniel.woods@objectpartners.com);

Java 8 introduz um conceito similar ao do Groovy


no que diz respeito a iterar colees, disponibilizando o
mtodo forEach, que substitui a maneira convencional de
percorrer listas.

emails.add(nemnesic@nemnesic.com);
List<String> gmails = emails.stream().filter( (String email) ->
email.endsWith(@gmail.com) ).collect(Collectors.toList());
assert gmails.get(0) == danielpwoods@gmail.com && gmails.get(1) ==
nemnesic@gmail.com;

List<Integer> list = new ArrayList<>();


list.add(1); list.add(2);
list.add(3); list.add(4);
list.forEach( (Integer item) -> System.out.println(item); );

Alm da iterao simplificada, o Groovy d aos


desenvolvedores uma variedade de outros atalhos
quando se trabalha com listas. O mtodo collect, por
exemplo, a abreviao para mapear elementos de uma
lista para novos tipos ou valores, coletando os resultados
em uma nova lista.

As extenses da API Collections do Groovy tornam


fcil a ordenao de listas fornecendo API um mtodo
sort. O mtodo sort tambm utilizar uma closure que
converte para um comparador durante a ordenao da
lista se uma lgica de ordenao especial for necessria.
Adicionalmente, se uma simples reverso da ordem da
lista necessria, o mtodo reverse pode ser chamado e
a ordem invertida.
def list = [2, 3, 4, 1]
assert list.sort() == [1, 2, 3, 4]

def list = [1, 2, 3, 4]

assert list.sort { a, b -> a-b <=> b } == [1, 4, 3, 2]

def newList = list.collect { n -> n * 5 }

assert list.reverse() == [2, 3, 4, 1]

assert newList == [5, 10, 15, 20]

Na implementao do Groovy, o mtodo collect recebe


um mapeamento como argumento, enquanto o Java 8
oferece uma implementao um pouco mais verbosa.
Usando a API Stream, os desenvolvedores podem realizar
a mesma estratgia de mapeamento e coleta chamando
o mtodo map no componente stream da lista, em
seguida, chamar o mtodo collect a partir do stream que
retornado na etapa de mapeamento. A API Stream d
aos desenvolvedores a capacidade de efetuar facilmente

40 InfoQ Brasil

Trabalhando novamente com a API de Stream do Java


8, podemos ordenar a lista usando o mtodo sorted e
obter o resultado usando o mtodo toList do Collectors.
O mtodo sorted pode receber opcionalmente uma
funo de comparao como argumento (tal como uma
funo Lambda), ento uma lgica de ordenao especial
e reverso dos itens da lista so operaes facilmente
realizadas.
List<Integer> list = new ArrayList<>();

list.add(2); list.add(3);

strings.add(item3);

list.add(4); list.add(1);

strings = strings.stream().map(Helpers::modifier).collect(Collectors.

list = list.stream().sorted().collect(Collectors.toList());

toList());

assert list.get(0) == 1 && list.get(3) == 4;

assert edited_item1.equals(strings.get(0));

list = list.stream().sorted((Integer a, Integer b) ->

assert edited_item2.equals(strings.get(1));

Integer.valueOf(a-b).compareTo(b)).collect(Collectors.toList());

assert edited_item3.equals(strings.get(2));

assert list.get(0) == 1 && list.get(1) ==


4 && list.get(2) == 3 && list.get(3) == 2;
list = list.stream().sorted((Integer a, Integer b) -> b.compareTo(a)).
collect(Collectors.toList());
assert list.get(0) == 2 && list.get(3) == 1;

Quando usando APIs fluentes, como stream de lista,


isso pode rapidamente ser insustentvel para tratar
todos os processamentos dentro de uma funo closure
ou Lambda. Isso faz sentido, em alguns casos, como
delegar o processamento para um mtodo que adaptado
especialmente para essa unidade de trabalho.
No Groovy, podemos fazer isso passando a referncia
de um mtodo dentro da funo. Uma vez que um mtodo
referenciado usando o operador .&, ele convertido para
uma funo closure e pode ser passado para outro mtodo
como argumento. Intrinsecamente, isso proporciona
flexibilidade na implementao, uma vez que o cdigo de
processamento pode ser introduzido de fontes externas.
Os desenvolvedores podem agora organizar logicamente
o processamento dos mtodos obtendo uma arquitetura
de aplicao mais fcil de ser mantida e sustentvel.
def modifier(String item) {
edited_${item}
}
def list = [item1, item2, item3]
assert

list.collect(this.&modifier)

==

[edited_item1,

edited_

item2, edited_item3]
Desenvolvedores no Java 8 dispem da mesma flexibilidade atravs do
uso do operador :: para obter uma referncia do mtodo.
List<String> strings = new ArrayList<>();
strings.add(item1);
strings.add(item2);

Os mtodos de referncia podem ser passados como


argumentos para qualquer mtodo que necessita de uma
interface funcional. Por sua vez, os mtodos de referncia
tero a forma de interfaces funcionais e podem ser
tratadas como tal.
public interface MyFunctionalInterface {
boolean apply();
}
void caller(MyFunctionalInterface functionalInterface) {
assert functionalInterface.apply();
}
boolean myTrueMethod() {
return true;
}
caller(Streaming::myTrueMethod);

No Java 8, os desenvolvedores de bibliotecas podem


fazer mudanas nos contratos das interfaces sem que os
consumidores tenham que atualizar a forma de interagir
com as bibliotecas.
A traduo perfeita dos conceitos e estilos de
programao do Groovy para o Java 8 uma ponte
importante entre duas linguagens. O Groovy foi adotado
em grande escala no domnio da JVM por causa das
flexibilidades de herana e melhorias nas APIs existentes
do Java. Com muitas dessas melhorias enraizando no
Java 8, isso significa que a similaridade entre as duas
linguagens esto comeando a superar as diferenas, um
fato que este artigo pretende delinear. Para finalizar, os
desenvolvedores que possuem experincia em Groovy
tero uma curva de aprendizado pequena para aprender
e adaptar as novas APIs, funcionalidades e conceitos

Sobre o Autor
Daniel pode ser contatado atravs do email
danielpwoods@gmail.com ou pelo Twitter
@danveloper.
Daniel Woods consultor snior na Object Partners, Inc. Ele especialista
em Arquitetura de Aplicaes com Groovy e Grails, mantendo forte interesse em Java e outras linguagens baseadas na JVM.
eMag | Java: Presente e Futuro 41

NASHORN: COMBINANDO O PODER DO JAVA E


JAVASCRIPT NO JDK 8
por Oliver Zeigermann, traduzido por Rafael Sakurai
No JDK 8, o Nashorn substituiu o Rhino como motor padro de JavaScript do Java por oferecer melhorias de desempenho e compatibilidade.
O Avatar.js trouxe o popular modelo de programao do Node para o Nashorn, permitindo que muitos servidores de aplicaes JavaScript possam ser
executados no ambiente Java.

esde o JDK 6, o Java foi liberado contendo um


motor de JavaScript com base no Rhino da
Mozilla. Essa funcionalidade permite embarcar
cdigo JavaScript dentro do Java e at chamar no Java o
cdigo JavaScript embarcado. Alm disso, ele permite
a execuo de JavaScript atravs de linha de comando
usando o jrunscript. Isso bom o suficiente quando
no h necessidade de muito desempenho e possvel
conviver com um conjunto limitado das funcionalidades
do ECMAScript 3.
Comeando com o Nashorn do JDK 8 atualizando o
Rhino como motor embarcado de JavaScript no Java. O
Nashorn fornece suporte completo para a especificao
do ECMAScript 5.1 com mais algumas extenses. Permite
compilar o JavaScript em bytecode Java usando as novas
funcionalidades da linguagem com base na JSR 292,
incluindo o invokedynamic, que foi introduzido no JDK 7.

42 InfoQ Brasil

Isso fornece um desempenho de 2 a 10x a mais


que a antiga implementao do Rhino, apesar de ter o
desempenho um pouco inferior ao V8, o motor dentro
do Chrome e Node.js. Se estiver interessado nos detalhes
da implementao d uma olhada nesses slides do JVM
Language Summit de 2013.
Como o Nashorn vem com o JDK 8, ele d suporte s
interfaces funcionais, como veremos em mais detalhes
adiante.
Vamos comear com um exemplo bem simples. Primeiro
ser necessrio instalar o JDK 8 e o NetBeans, IntelliJ IDEA
ou Eclipse. Essas IDEs fornecem ao menos o suporte bsico
de JavaScript integrado com o desenvolvimento. Vamos
criar um simples projeto Java contendo dois arquivos de
exemplo e em seguida executaremos o programa, como
mostrado na figura a seguir:

Na linha 12 usamos o mtodo eval para avaliar


qualquer cdigo JavaScript. Nesse caso apenas
carregamos o arquivo JavaScript principal e o
avaliamos. No se preocupe com o print no cdigo,
ele pode no parecer familiar porque no construmos
essa funo no JavaScript, mas o Nashorn fornece
essa e outras funes por convenincia, que so
convenientes no ambiente de scripting. Tambm seria
possvel passar o comando de impresso do hello

world direto como argumento para o eval, mas


ter o JavaScript em seu prprio arquivo abre todo um
mundo de ferramental para ele.
Atualmente o Eclipse no possui um suporte
dedicado para o Nashorn atravs do projeto da
Ferramenta de Desenvolvimento de JavaScript (JSDT),
no entanto suporta o ferramental bsico e a edio de
JavaScript.

eMag | Java: Presente e Futuro 43

O IntelliJ IDEA 13.1 (edio da comunidade e final)


fornece excelente suporte ao JavaScript e Nashorn. H
funcionalidades completas para depurar e tambm
permitir o refatoramento que sincroniza o Java com o
JavaScript; ento por exemplo, se renomear uma classe
Java que referenciada no JavaScript ou se renomear
um arquivo JavaScript que usado no Java, a IDE

modificar as referncias correspondentes entre as


linguagens.
A seguir temos um exemplo que permite depurar
uma chamada ao JavaScript atravs do Java (note que
o NetBeans tambm fornece depurao de JavaScript
como mostrado na figura a seguir):

Pode-se dizer que o ferramental bom e que a nova


implementao corrige os problemas de desempenho
bem como o problema de estar em conformidade com
o JavaScript, mas por que devemos usa-lo? Uma razo
pode ser o script em geral. Algumas vezes pode ser til
para tratar alguns tipos de strings e deixar apenas que
seja interpretada. Algumas vezes pode ser bom no
ter um compilador no caminho ou no se preocupar
com tipos estticos, ou talvez o interesse no modelo de
programao do Node.js, que pode ser usado no Java
como veremos no final desse artigo. H tambm o caso
do desenvolvimento no JavaFX que ser muito mais
rpido usando JavaScript do que apenas Java.
O motor do Nashorn pode ser executado atravs da

lo sem argumentos para abrir o modo interativo, ou


pode informar o nome do arquivo JavaScript que
deseja executar, ou pode usar para substituir o shell
script, exemplo:
#!/usr/bin/env jjs
var name = $ARG[0];
print(name ? Hello, ${name}! : Hello, world!);

Para passar argumentos no programa atravs do


jjs, utilize o prefixo --. Dessa forma podemos ter
uma chamada como a seguinte:
./hello-script.js -- Joe

Shell scripts
linha de comando usando o comando jjs. Pode executa-

44 InfoQ Brasil

Sem o prefixo --, o parmetro ser interpretado


como o nome do arquivo.

Passando dados para o Java e vice-versa


Como mencionado anteriormente, possvel
chamar o JavaScript direto do cdigo Java atravs
do motor chamado ScriptEngine e chamando seu
mtodo eval. possvel passar dados explicitamente
como strings ...
ScriptEngineManager scriptEngineManager
= new ScriptEngineManager();

}
});
var th = new MyThread();
th.start();
th.join();

Note que a maneira cannica de acessar uma classe


atravs do Nashorn usando o Java.type e estendendo
uma classe atravs do Java.exend.

ScriptEngine nashorn = scriptEngineManager.


getEngineByName(nashorn);
String name = Olli;
nashorn.eval(print(\ + name + \));

ou pode passar referncias do Java que podem


ser acessadas como variveis globais dentro do motor
de JavaScript:
int valueIn = 10;
SimpleBindings simpleBindings = new SimpleBindings();

Linguagem funcional

Por todos os aspectos, com o lanamento do JDK


8, o Java tornou-se - pelo menos at certo ponto - uma
linguagem funcional. Agora possvel usar funes
de ordem superior nas colees, por exemplo para
iterar sobre um conjunto de elementos. Uma funo
de ordem superior uma funo que tem outra funo
como parmetro e faz algo significativo com ela. Veja
um exemplo em Java:

simpleBindings.put(globalValue, valueIn);
nashorn.eval(print (globalValue), simpleBindings);

List<Integer> list = Arrays.asList(3, 4, 1, 2);

O resultado da execuo do JavaScript devolvido

list.forEach(new Consumer() {

atravs do mtodo eval do motor:

@Override

Integer result = (Integer) nashorn.eval(1 + 2);

public void accept(Object o) {


System.out.println(o);

assert(result == 3);
}

Usando classes Java no Nashorn

Como mencionado anteriormente, uma das


funcionalidades mais poderosas do Nashorn o uso de
classes do Java dentro do JavaScript. possvel tanto
acessar as classes e criar instncias como tambm
criar subclasses delas, chamar membros estticos
e fazer virtualmente qualquer coisa que possvel
diretamente no Java.
Como um exemplo, vamos dar uma olhada em
threads. O JavaScript no tem nenhuma funcionalidade
da linguagem para tratar concorrncia e todos os
ambientes de execuo comuns so de processos
nicos ou pelo menos sem qualquer compartilhamento
de estado. interessante ver que no ambiente do
Nashorn o JavaScript pode de fato ser executado
concorrentemente e com compartilhamento de estado,
tal como no Java:

});

Nesse exemplo, ao invs de iterar sobre os


elementos usando um lao externo como fazemos
tradicionalmente, agora passamos uma funo
Consumer para o mtodo forEach, uma operao
de ordem superior realiza um lao interno e executa
o mtodo accept do Consumer, percorrendo cada
elemento da coleo, um a um.
Como mencionado, a abordagem da linguagem
funcional para tal funo de ordem superior aceitaria
um parmetro de funo, em vez de um objeto. A
passagem como referncias para as funes em si, no
algo tradicional fornecido no Java, o JDK 8 agora possui
alguns tipos sintticos para expressar justamente o
uso de expresses lambda (tambm conhecidas como
closures). Por exemplo:
List<Integer> list = Arrays.asList(3, 4, 1, 2);

// assim que obtemos acesso classe Thread do Java.

list.forEach(el -> System.out.println(el));

var Thread = Java.type(java.lang.Thread);


// cria a subclasse com o mtodo run.
var MyThread = Java.extend(Thread, {
run: function() {
print(Run in separate thread);

Nesse caso o parmetro para o forEach tem o


formato de uma referncia de funo. Isso possvel
porque o Consumer uma interface funcional (algumas
vezes chamado de tipo de Mtodo Abstrato Simples, ou
do ingls Single Abstract Method - SAM).

eMag | Java: Presente e Futuro 45

Ento, porque abordamos lambdas na discusso


sobre Nashorn? Porque no JavaScript podemos
escrever cdigos como esse e o Nashorn est
especialmente preparado para fazer a ligao entre o
Java e o JavaScript nesse caso. Em particular, porque
permite passar funes escritas em JavaScript como
implentaes de interfaces funcionais (tipo SAM).
Vejamos alguns simples exemplos de cdigo
JavaScript que fazem coisas iguais as feitas com
cdigo Java. Note que no h uma forma de
construo de listas no JavaScript, apenas arrays; mas
esses arrays so dimensionados dinamicamente e
tem mtodos para comparao deles com uma lista
em Java. Ento, nesse exemplo estamos chamando o
mtodo forEach de um array em JavaScript:

extenses que so usadas na documentao da Oracle


e podemos nos familiar com elas.
Primeiro vamos configurar o cenrio para a
primeira extenso. Como visto anteriormente
podemos estender classes Java atravs do JavaScript
usando o Java.extend. Se quiser criar uma subclasse de
uma classe Java abstrata ou implementar um interface
podemos usar uma sintaxe mais conveniente. Nesse
caso possvel chamar virtualmente o construtor
de uma classe abstrata ou interface e passar um
objeto literal JavaScript que descreve os mtodos
implementados. As literais do objeto JavaScript so
apenas pares de nome e valor, muito parecido com
o formato JSON. Nesse exemplo foi implementado a
interface Runnable:

var jsArray = [4,1,3,2];

var r = new java.lang.Runnable({


run: function() {

jsArray.forEach(function(el) { print(el) } );

print(running...\n);

A similaridade bvia; mas isso no tudo.


Podemos tambm converter um array em JavaScript
para uma lista em Java:
var list = java.util.Arrays.asList(jsArray);

Esse cdigo JavaScript executa dentro do Nashorn.


Como isso agora uma lista do Java, podemos
chamar o mtodo forEach. Note que esse no o
mesmo mtodo forEach que chamamos no array
em JavaScript, mas sim o mtodo forEach definido
nas collections. Ainda, podemos passar uma funo
simples em JavaScript:
list.forEach(function(el) { print(el) } );

O Nashorn permite que passemos funes em


JavaScript como referncia, nos locais que esperam
interfaces funcionais (tipo SAM). Portanto, isso no
possvel apenas no Java, mas tambm no JavaScript.
A prxima verso do ECMAScript - que esperase a verso final para esse ano - incluir uma sintaxe
curta para funes que permitir cdigos similares
aos lambdas em Java, exceto que no JavaScript ser
usado seta dupla =>. Isso facilitar ainda mais o
alinhamento entre as linguagens.

Dialeto especial do JavaScript no Nashorn


O Nashorn suporta atualmente a verso 5.1
do ECMAScript e mais algumas extenses. No
recomendo o uso dessas extenses porque no se
parecem com Java e nem JavaScript, parece algo no
natural para os desenvolvedores. No entanto h duas

46 InfoQ Brasil

}
});

Nesse exemplo estamos virtualmente chamando


o construtor de Runnable com um objeto literal que
especifica a implementao do mtodo run. Note que,
isso algo que a implementao do Nashorn possui,
em outros casos isso no seria possvel apenas com
JavaScript.
O cdigo desse exemplo bem parecido com a
implementao de uma interface usando uma classe
interna annima em Java. Isso nos leva a primeira
extenso, que deixa passar o ltimo parmetro aps o
parnteses ) de fechamento durante a chamada do
construtor. Fazendo isso, o cdigo ficaria como esse ...
var r = new java.lang.Runnable() {
run: function() {
print(running...\n);
}
};

que faz exatamente a mesma coisa, mas tem


uma semelhana ainda maior com o Java.
A segunda extenso mais usada um atalho
para as funes que permite omitir ambas as chaves
bem como a instruo de retorno, para que o corpo
do mtodo possa ser em uma nica linha. Assim, o
exemplo da sesso anterior ...
list.forEach(function(el) { print(el) } );
pode ser expresso de forma ligeiramente mais conciso:
list.forEach(function(el) print(el));

Avatar.js
Vimos que com o Nashorn temos um bom motor
de JavaScript embarcado no Java. Tambm vimos que
o Nashorn pode acessar as classes do Java. O Avatar.js
vai um passo alm e traz o modelo de programao
do Node, APIs e os mdulos do ecossistema para a
plataforma Java. Para entender o que isso significa
e porque excitante, primeiro vamos entender o que
o Node.
O Node basicamente uma extrao do motor de
JavaScript V8 do Chrome que pode ser executado
atravs de linhas de comando, sem precisar de
um navegador. Isso permite que o JavaScript seja
executado no apenas no navegador, mas tambm no
lado servidor. Para executar o JavaScript no servidor
de uma forma significativa, ser necessrio acessar
pelo menos o sistema de arquivos e a rede. Para fazer
isso, o Node possui uma biblioteca chamada libuv
que faz isso de maneira assncrona. Na prtica, isso
significa que as chamadas ao sistema operacional no
ficam bloqueadas mesmo que demorem algum tempo
para responder. Ao invs de bloquear, fornecida
uma funo de callback que ser acionada uma vez
que a chamada terminar, entregando os resultados,
se houver algum.
H diversas empresas que usam o Node para
aplicaes srias, como o Walmart e o Paypal.
Vejamos um pequeno exemplo de JavaScript que
foi adaptado do site do Node:
// carrega o mdulo http (isso bloqueante)
para tratar requisies http.
var http = require(http);
// quando h uma requisio, retornamos Hello, World\n.
function handleRequest(req, res) {
res.writeHead(200, {Content-Type: text/plain});
res.end(Hello, World\n);
}
// Vamos escutar a porta 1337 do localhost
// e dar um handleRequest quando a chamada voltar.
// Veja aqui a forma sem bloqueio / assncrona.
http.createServer(handleRequest).listen(1337, 127.0.0.1);
// registramos no console para garantir
que a aplicao foi inicializada.
console.log(Get your hello at http://127.0.0.1:1337/);

Para executar esse cdigo ser necessrio instalar


o Node, salvar o cdigos JavaScript no arquivo e
finalmente chamar o Node passando o arquivo como
parmetro.

O objetivo do Avatar.js fornecer a mesma


API central como o Node ligando o libuv com as
classes Java e ento torn-lo acessvel ao JavaScript.
Mesmo que isso possa parecer complicado, funciona
surpreendemente bem. O Avatar.js suporta diversos
mdulos Node e suporta o express - o principal
framework web para Node - indicando que isso pode
funcionar com diversos projetos existentes.
O Avatar.js possui uma distribuio binria que
pode ser encontrada no site do projeto bem como os
passos para a sua instalao.
Um vez que tenha configurado os binrios e
colocados na pasta lib, podemos ento chamar o
framework Avatar.js usando algo como:
java -Djava.library.path=lib -jar lib/
avatar-js.jar helloWorld.js

Assumimos que no servidor de demonstrao est


salvo um arquivo chamado helloWorld.js.
Novamente perguntamos, porque isso til? As
pessoas na Oracle (slide 10) viram diversos casos de
uso para uma biblioteca. Concordo principalmente
com dois deles:
1. Se temos uma aplicao Node e queremos usar
certas bibliotecas do Java para complementar a API
do Node;
2. Se queremos trocar para as APIs do JavaScript e
Node, mas precisamos embarcar o cdigo Java legado
em partes ou completamente.
Ambos casos de uso funcionam usando o Avatar.
js e chamando qualquer classe necessria do Java
atravs do cdigo JavaScript, que suportado pelo
Nashorn.
Vejamos um exemplo do primeiro uso. O JavaScript
tem atualmente apenas um nico tipo para expressar
nmeros chamado number. Sendo equivalente ao
tipo de preciso do double do Java, com as mesmas
limitaes; o number do JavaScript, como o double
do Java no capaz de expressar tamanho e preciso
arbitrria, por exemplo para tratar de valores
monetrios.
No Java podemos usar o BigDecimal, que suporta
exatamente isso. Mas o JavaScript no tem uma
construo equivalente, ento podemos acessar a
classe BigDecimal atravs do cdigo JavaScript e ter
o mesmo tratamento seguro de valores monetrios.
Vejamos um exemplo de web service que calcula o
percentual de alguma quantia. Primeiro precisamos
de uma funo que faz o clculo real:

eMag | Java: Presente e Futuro 47

var BigDecimal = Java.type(java.math.BigDecimal);


function calculatePercentage(amount, percentage) {
var result = new BigDecimal(amount).multiply(
new BigDecimal(percentage)).divide(
new BigDecimal(100), 2,
BigDecimal.ROUND_HALF_EVEN);
return result.toPlainString();
}

No JavaScript no h declarao de tipos, mas fora


isso, o cdigo se parece muito com o cdigo Java,
como mostrado a seguir:
public static String calculate(String
amount, String percentage) {
BigDecimal result = new BigDecimal(amount).multiply(
new BigDecimal(percentage)).divide(
new BigDecimal(100), 2,
BigDecimal.ROUND_HALF_EVEN);

usando o navegador web, obtemos a resposta


correta 7567230000000000006600158.73 que seria
impossvel de calcular usando apenas o tipo number do JavaScript.
O segundo caso pode fazer mais sentido quando
decidimos migrar uma aplicao JEE existente para
JavaScript e Node. Nesse caso podemos facilmente
acessar todos os servios existentes com o JavaScript.
Outro caso de uso relacionado, podemos ter uma
nova parte da funcionalidade do servidor construdo
usando JavaScript e Node que pode se beneficiar dos
servios JEE existentes.
Indo na mesma direo, h tambm o Projeto Avatar que baseado no Avatar.js. Os detalhes vo alm
do escopo desse artigo, mas para ter uma viso rpida
d uma olhada no anncio feito pela Oracle. A ideia
bsica escrever a aplicao em JavaScript e acessar
os servios JEE. O Projeto Avatar vem com uma distribuio binria combinanda com o Avatar.js mas
precisa do Glassfish para instalar e desenvolver.

return result.toPlainString();
}

Apenas precisamos substituir a funo handleRequest do Node, como no exemplo anterior, para completarmos o cdigo. Como esse:
// Carrega o mdulo utilitrio url para converter a url.
var url = require(url);
function handleRequest(req, res) {
// /calculate o caminho do web service.
if (url.parse(req.url).pathname === /calculate) {
var query = url.parse(req.url, true).query;
// Quantia e percentual so passados como

O projeto Nashorn aumentou a implementao


original do Rhino no JDK 6 fornecendo melhorias
de desempenho para aplicaes de execuo longa,
por exemplo quando usamos dentro de um servidor
de aplicaes web. O Nashorn integra o Java com
o JavaScript e permite usar as novas expresses
lambdas do JDK 8. Uma inovao real vem com o
Avatar.js que fornece integrao com o Java EE e o
cdigo JavaScript sendo amplamente compatvel com
o padro para programao no servidor JavaScript.
Os exemplos completos, incluindo o binrio do
Avatar.js para Mac OS X, esto disponveis no Github.

parmentro de consulta da requisio.


var result = calculatePercentage(query.amount,
query.percentage);
res.writeHead(200, {Content-Type: text/plain});
res.end(result + \n);
}
}

Usamos o segundo mdulo principal do Node


para processar a URL da requisio para converter os
parmetros da consulta em quantia e porcentagem.
Aps iniciar o servidor, se fizermos uma requisio como ...
http://localhost:1337/calculate?amount=99700000000000000086958613&percentage=7.59

48 InfoQ Brasil

Sobre o Autor
Oliver Zeigermann consultor de arquitetura e desenvolvimento de software, e Coach em Hamburg, Alemanha. Atualmente tem se concentrado em usar JavaScript em aplicaes corporativas.

JAVA 9 E ALM: BRIAN GOETZ E JOHN ROSE


FALAM SOBRE O FUTURO DO JAVA
O InfoQ convidou Brian Goetz (arquiteto da linguagem Java) e John Rose (arquiteto da JVM) para discutir a funcionalidades previstas
para o Java 9 e verses posteriores.
InfoQ: Vocs distinguem entre a reificao de tipos
genricos e a especializao primitiva. Podem falar mais
sobre isso?
Goetz: Os desenvolvedores no se sentem bem com a remoo
de informaes de tipos (type erasure); tm o sentimento de estar
fazendo alguma coisa errada. Na verdade, o type erasure til e
aplicar a tcnica gera poucos problemas. Por outro lado, o Boxing
ineficiente, usa mais memria, enfraquece a localidade e demanda
mais do Garbage Collector. timo que cdigo como ArrayList<T>
possa abstrair diversos Ts. Mas o desenvolvedor no deve pagar o
preo do boxing para obter a abstrao dos tipos genricos quando tudo o que precisa de um Array de tipos inteiros primitivos.

InfoQ.com: E quanto s formas de type erasure em interfaces, com perda de informao, como em sobrecargas?
List<String> e List<Map<String, Integer>> seriam tipos
distintos no Java 10?
Goetz: List<String> e List<Integer> sempre foram tipos diferentes, mas esses dois tipos so representados pela mesma classe em
tempo de execuo. A remoo de informao de tipos (erasure)
impede que se descubra se um tipo List foi definido como List<String> ou um List<Integer> antes de a informao ser removida.
Uma traduo heterognea completa de tipos genricos, como
a usada nos templates do C++, mapearia cada um desses tipos para

uma classe separada, sem relao entre essas classes. No o que


estamos propondo. Mas alguns tipos genricos como List<int> podem ser representados por uma classe diferente de List<String>.
Ou seja, o mapeamento de tipos em tempo de compilao para
classes em tempo de execuo pode funcionar de forma diferente,
na criao de listas para tipos primitivos e em listas para referncia
de objetos.
Rose: Isso significa que as estruturas equivalentes de tipos de
valor que tiveram informao de tipos removida aparecero no
bytecode.
Goetz: Dizendo de outra maneira: desenvolvedores que esto
usando (raw types) ou <?> para evitar fazer certas decises, tero
de aprender como fazer corretamente. Assim que tivermos especializao e valores de tipo (value types), o uso de raw types ser
cada vez menos aceito. Se voc no sabe usar bem tipos genricos,
chegou a hora de aprender. J estamos percebemos coisa do gnero com os lambdas. Se voc consultar o Stack Overflow, vai ver
muitas perguntas do tipo: por que no consigo fazer isso e aquilo
com um lambda?. So questes relacionadas ao uso incorreto de
tipos genricos, o que faz o sistema de inferncia de tipos falhar.

InfoQ.com: Falem um pouco sobre a possibilidade de


Optional ser um tipo proto-value
Goetz: Havia uma pequena otimizao potencial ao migrar um
tipo de referncia do Java 8 para um tipo de valor no Java 10. Ba-

eMag | Java: Presente e Futuro 49

sicamente, preparamos o terreno indicando aos desenvolvedores


que no devem depender que certas propriedades (como verificao de identidade) sejam verdadeiras para os tipos que podem se
tornar value types no futuro. Sempre que a migrao para tipos de
valor se mostrar til na prtica, ela poder acontecer.

InfoQ.com: Haver JSRs para os projetos Panama e o


Valhalla, ou para alguma tecnologia vinda deles? Quando
saberemos em qual release do Java sero includos?
Rose: sempre melhor iniciar uma JSR quando j se tem ideia
de onde se quer chegar. A criao de JSRs deve acontecer idealmente entre dois momentos: depois de determinar a verso do JDK
e antes de se ter um prottipo bem aceito.
Goetz: Exatamente. Isso similar com o que aconteceu com os
lambdas, que iniciamos juntamente com o OpenJDK. A JSR foi lanada assim que definimos os critrios de sucesso para o projeto os
especialistas que formariam o Expert Group da JSR.
Rose: As JSRs trazem muitos benefcios, mas necessrio um
bom ponto de partida especialmente para no acontecer de formarmos uma equipe cedo depois e desperdiar o tempo dos especialistas.
Goetz: Temos sorte que agora todos os aspectos legais para
desenvolver as JSRs no OpenJDK esto resolvidos. Assim podemos
desenvolv-las de forma aberta desde o incio. Com relao a releases, acompanhe os repositrios do Valhalla, especialmente as
pequenas migraes entre os repositrios do JDK9 e JDK 10.

InfoQ.com: O que dizem sobre os projetos com novas


abordagens para acesso a dados, como os Packed Objects
da IBM e o ObjectLayout de Gil Tene?

Rose: O Java tem 20 anos de idade e ouvem-se reclamaes sobre arrays desde a primeira verso. Estamos convergindo para uma
API que permita atingir dados unidimensionais (flat data). Estamos
chegando perto de iniciar prottipos que o objetivo do Projeto
Panama. A IBM foi envolvida desde o incio; h uma lista de discusso especial de que os engenheiros da VM da empresa podem participar. So necessrias mudanas na linguagem, por exemplo os
value types e mudanas em algumas premissas.

InfoQ.com: A Hazelcast, entre outras empresas, tem


pedido por arrays usando ndices do tipo long. Isso possvel?
Rose: Todas as novas APIs para dados em que estamos trabalhando tm ndices long.
Goetz: Estamos trabalhando nisso, mas temos que lembrar que
com relao a novas funcionalidades h um nmero muito grande
de combinaes possveis: em esparsidade, tamanho, leitura e escrita ou somente leitura. Os desenvolvedores tm diferentes necessidades e necessrio priorizar.
Rose: verdade. H muitos graus de liberdade, como em pizzas! No queremos tratar uma pizza de cogumelos e cebolas
como uma combinao completamente diferente de uma pizza
com cebolas e pimentas. Isso nos levaria a uma exploso combinatria. Queremos, em vez disso, que se possa dizer escolha vrias
coberturas. Ainda estamos trabalhando para definir o cardpio
a ser oferecido
Um padro de arquitetura comum separar os dados gerenciados pela aplicao. Usurios tm custos incrementais de gerenciamento, portanto vo querer gerenciar os dados eles mesmos. Isso
leva a um nmero grande de bytes formatados pela aplicao, o
que leva diretamente ao acesso nativo a dados.

Sobre os Participantes
Brian Goetz desenvolvedor profissional h mais
de 20 anos e autor do popular livro Java Concurrency in Practice. Escreveu mais de 75 artigos sobre
desenvolvimento em Java e foi lder da especificao que trouxe os lambdas para a linguagem (JSR
335). Goetz o Arquiteto da Linguage Java na Oracle.
John Rose lder do projeto Da Vinci no OpenJDK.
Liderou a JSR 292, que introduziu no Java o suporte
a invocaes dinmicas e profiling de tipos. Antes
disso, participou da criao dos inner cla

50 InfoQ Brasil

NOVOS
HORIZONTES
DO
JAVA
por Ben Evans, Victor Grazi e Abraham Marn Prez.

Traduo/Adaptao: Leonardo Galvo, Wellington Pinheiro e Wellington Soares


A renovao da linguagem e plataforma Java est acelerando. Com muitas novas caractersticas no horizonte para verso 9 e alm, o Java continua
avanando em qualidade, desempenho e facilidade de uso. Conhea nesse artigo uma seleo do que est por vir.

Se havia dvidas que o Java era o padro de fato para


desenvolvimento no lado servidor, o Java 8 resolveu
essa questo. Agora o mundo aguarda ansiosamente
pelo Java 9, atualmente agendado para maro de 2017.
H muitas coisas no horizonte para verso 9 e alm. O
projeto Jigsaw pode ser considerado o carro-chefe do Java
9; est destinado a trazer programao modular ao mainstream do Java. Depois de anos de negociaes e mltiplas
JSRs e JEPs, o projeto est assumindo sua forma final.
Outras novas funcionalidades do Java 9 so o suporte
a HTTP/2 e o REPL, alm de um modelo de memria renovado e novas tcnicas de garbage collection. O HTTP/2
trata de problema antigos do suporte enferrujado ao
HTTP no Java atual.
J o REPL permite a desenvolvedores testar cdigos
interativamente, sem a necessidade de se preocupar com
estruturas de classes e compiladores. E o novo coletor de
lixo Garbage First (tambm conhecido como G1GC) promete suportar heaps imensos com o mnimo de interrupes.
A inovaes, porm, vo bem alm dessa lista. Nas
sees seguintes compilamos um pequeno histrico da

Primeiros anncios
evoluo do Java 9, adaptando vrias notcias e artigos do
InfoQ, Conhea o que est a caminho!
O Java 9 teve incio em agosto de 2014, quandi a Oracle
anunciou o primeiro grupo de JEPs para o Java 9 (JEP
= Java Enhancement Proposal Proposta de Aperfeioamento).
Os JEPs fazem parte de um novo processo que permite
funcionalidades da linguagem e VM do Java para ser exploradas sem a necessidade de um processo de especificao completo como o atual JSR. Isso permite que o escopo
dos JEPs seja menor e mais focado e que tratem so especficos implementao OpenJDK. JEPs bem sucedidas podem ento ser convertidas em pedidos de padronizao
no JSR ou includas em padres existentes.
Trs novas APIs foram anunciadas inicialmente:
Process API Updates para interao com processos
de sistema operacional no baseados em Java;
Um novo HTTP Client que inclui suporte a HTTP/2;
Uma nova API leve para JSON, que deve ser construda com base no suporte a JSON (JSR 353).
H tambm trs novidades voltadas ao desempenho:

eMag | Java: Presente e Futuro 51

Melhoria em locks de conteno, para aumento de

desempenho quando mltiplos threads competem


pelo acesso a objetos;
Segmentao do cache de cdigo do JIT, para melhor desempenho do compilador Just in Time em
grandes aplicaes;
Novas melhorias no compilador Java inteligente, o
sjavac; essa ferramenta promete compilao paralela e compartilhada, entre outras melhorias.
Quanto ao JEP 201 (Cdigo Fonte Modular), ele no era
neste momento o o projeto Jigsaw prometido para verses
anteriores do Java mas sim um trabalho de limpeza no
OpenJDK preparando as bases para a modularidade.
Esse JEP estabeleceu limites claros para cada mdulo
ao mesmo tempo que o prprio JDK est sendo construdo.

Outras novidades

Foi um primeiro passo na direo da modularidade completa, ainda que os mdulos no estivessem visveis ao
desenvolvedor em tempo de execuo.
Em novembro de 2014, a Oracle anunciou outras funcionalidades do Java 9, com destaque para a modularidade da plataforma. Veja outras mudanas anunciadas:
Logging unificado na JVM uma grande reviso
no mecanismo interno de notificao de eventos na
JVM, permitindo substituir o atual sistema de logging por um sistema comum e unificado, possibilitando que diversos componentes compartilhem o
mecanismo de logging;
Remoo de combinaes de GC obsoletas a remoo das combinaes: DefNew + CMS, ParNew
+ SerialOld e Incremental CMS. Estas haviam sido
marcadas como obsoletas no Java 8;
Mais controle sobre o compilador melhoria no
controle sobre o compilador Hotspot JIT, permitindo adicionar opes para cada mtodo a ser compilado e alterar as opces em runtime. Por exemplo,
adicionar diretivas para habilitar ou desabilitar
uma otimizao especfica para determinado mtodo, remover a opo de o mtodo ser inline ou at
mesmo instalar uma diretiva durante a execuo e
verificar seu resultado;
Project Coin atualizado Ajustes em alguns detalhes originados no Java 7 (Project Coin) que trouxe
mudanas na linguagem. Sero permitidos @SafeVargs em mtodos privados, o operador diamond
com inner classes, entre outras mudanas.
Novidades incluem tambm o trmino do projeto
de remoo de warnings e uma limpeza no gerenciador
de importao. Ao importar classes obsoletas, no sero
mais disparados alertas. Alm disso, alguns problemas
antigos na resoluo de tipos no javac sero corrigidos.
O suporte a algumas tecnologias modernas tambm

52 InfoQ Brasil

foi anunciado, incluindo o Datagram Transport Layer Security (DTLS), e uma atualizao da ferramenta Javadoc
para gerao de HTML5.
As JEPs tambm indicam que a especializao de tipos
primitivos em tipos genricos (para permitir estruturas
como List<int>) no est mais planejada para o JDK9, mas
sim para o JDK10.

Data final quase definida, com alguns sacrifcios


Em julho de 2016, Mark Reinhold, Arquiteto Chefe da
Plataforma Java, sugeriu um mtodo para avaliar coletivamente o trabalho restante em JEPs inacabadas, e decidir
se ser atrasado o Java 9 ainda mais para acomodar as ltima mudanas ou se sero retirados JEPs pendentes do
escopo da verso 9. O processo est em andamento, mas
tudo indica que deve haver uma combinao dessas duas
estratgias.
Por um lado, h uma conjunto fundamental de funcionalidades que do sentido nova verso. Para esses,
a data final tem de ser adiada, a fim de incluir as funcionalidades centrais. Por outro lado, Reinhold enfatiza a
importncia de se estabelecer um ritmo previsvel para
novas verses. Ele percebe que funcionalidades no-fundamentais devem ser removidas do escopo se no forem
terminadas a tempo.
Esse raciocnio est alinhado com o processo proposto
para seleo de JEPs. Desse modo, espera-se que os lderes
das JEPs solicitem uma prorrogao do prazo, indicando a
data estimada de entrega ou comuniquem a sua sada
do Java 9. No caso de prorrogao, um processo de reviso
ir determinar se a extenso ser concedida ou no.
Atualmente 11 JEPs esto em anlise de um total de
82.
Entre os JEPs em risco de sarem do Java 9, a julgar pelo
estado do issue tracker no momento de escrita, dez solicitaram prorrogao do prazo (com sete j aprovados). A
data de entrega revista para estas JEPs 1 de setembro,
o que significa atraso de cerca de trs meses levando o
lanamento do Java 9 para junho de 2017.
Quatro JEPs seriam removidos do release para evitar
novos atrasos:
JEP 110 Cliente HTTP / 2
JEP 227 Depreciao melhorada
JEP 282 JLINK
JEP 284 Novo sistema de builds do HotSpot
Embora ainda no haja definio final, as decises recentes tendem a estabelecer a forma definitiva do Java 9.
Porm, se os JEPs acima forem mesmo removidos, uma
anlise mais aprofundada ser necessria para avaliar seu impacto, especialmente com relao ao JEP 282
(JLINK), que faz parte do sistema de mdulos, central
nova verso do Java.

eMag | Java: Presente e Futuro 53

You might also like