O documento resume 55 novas funcionalidades do Java 7, incluindo: literais binários e numéricos com underline, strings no switch, gerenciamento automático de recursos com try-with-resources, e novas APIs para concorrência, arquivos e números aleatórios.
2. As 55 funcionalidades do Java 7 que
você (provavelmete) nunca ouviu falar
• 55 minutos – 55 slides
• Ignite Format
• Sem parar!
• Sem voltar atrás
• Perguntas? Tudo bem, mas somente se ainda sobrar tempo
nesse slide (caso contrário, deixe para mais tarde)
• A especificação de requisitos do Java 7 tem mais de 2000
mudanças. Temos aqui 55 das mais relevantes…
2
2
4. “Underline” em literais numéricos
• Válido:
int mascara = 0b1010_1010_1010;
long grandao = 9_223_783_036_967_937L;
long numeroDoCartao = 1234_5678_9012_3456L;
long cadastroNoSUS = 999_99_9999L;
float pi = 3.14_15F;
Long bytesHex = 0xFF_EC_DE_5E;
long palavrasHex = 0xCAFE_BFFE;
• Inválido:
float pi1 = 3_.1415F; float pi2 = 3._1415F;
long nSUS = 999_99_9999_L;
int x1 = _52; int x1 = 52_;
int x2 = 0_x52; int x2 = 0x_52;
4
4
5. Strings na condição do switch
int nomeDoMesParaDias(String s, int ano) {
switch(s) {
case "Abril": case "Junho":
case "Setembro": case "Novembro":
return 30;
case "Janeiro": case "Março":
case "Maio": case "Julho":
case "Agosto": case "Dezembro":
return 31;
Você sabia que isso
case "Fevereiro”: geralmente produz byte codes
...
default: mais eficientes do que uma
... instrução if-then-else? Case
sensitive!
5
5
6. Gerenciamento automático de recursos
try (InputStream in = new FileInputStream(src),
OutputStream out = new FileOutputStream(dest))
{
byte[] buf = new byte[8192];
int n;
while (n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
• Nova superinterface java.lang.AutoCloseable
• Todos AutoCloseable (throws Exception) e tipos que estendem
java.io.Closeable (throws IOException) são utilizáveis com “try-
with-resources”
• Qualquer um que tenha void close() é um candidato
• JDBC 4.1 também foi adaptada como AutoCloseable
6
6
7. Exceções suprimidas
java.io.IOException
at Suppress.write(Suppress.java:19)
at Suppress.main(Suppress.java:8)
Suppressed: java.io.IOException
at Suppress.close(Suppress.java:24)
at Suppress.main(Suppress.java:9)
Suppressed: java.io.IOException
at Suppress.close(Suppress.java:24)
at Suppress.main(Suppress.java:9)
Throwable.getSuppressed(); // Returns Throwable[]
Throwable.addSuppressed(aThrowable);
7
7
9. Rethrow mais preciso
public void foo(String bar)
throws FirstException, SecondException {
try {
// Código que pode lançar tanto
// FirstException como SecondException
}
catch (Exception e) {
throw e;
}
}
• Antes do Java 7, esse código não compilaria. As exceções do throws
deveriam corresponder aos tipos das capturas – foo deveria ter um “throws
Exception”
• Java 7 adiciona o suporte para isso contanto que o bloco do try chame
todas as exceções da cláusula throws e que a variável na cláusula do catch
seja relançada e as exceções não sejam pegas por outro catch
9
9
10. O “Operador diamante” funciona de
várias formas…
• O compilador infere o tipo à partir do diamante (<>)
List<String> listaStr = new ArrayList<>();
OU
List<Map<String, List<String>> strList =
new ArrayList<>();
OU
Foo<Bar> foo = new Foo<>();
foo.mergeFoo(new Foo<>());
10
10
11. Warnings dos argumentos– Rasura
class Test {
public static void main(String... args) {
List<List<String>> monthsInTwoLanguages =
Arrays.asList(Arrays.asList("January",
"February"),
Arrays.asList("Gennaio",
"Febbraio" ));
}
} Test.java:7: warning:
[unchecked] unchecked generic array creation
for varargs parameter of type List<String>[]
Arrays.asList(Arrays.asList("January",
^
1 warning
@SuppressWarnings(value = “unchecked”) // at call
@SafeVarargs // at declaration
11
11
12. Funcionalidades do Java NIO.2 -
Tipos auxiliares
Três importantes tipos auxiliares no Java 7
• Classe java.nio.file.Files
• Métodos exclusivamente estáticos para trabalhar com arquivos,
diretórios e outros tipos de registros
• Classe java.nio.file.Paths
• Métodos exclusivamente estáticos para retornar um Path através da
conversão de String ou um URI (Uniform Resource Identifier)
• Interface java.nio.file.Path
• Usada para objetos que representam a localização de um arquivo no
sistema de arquivos, normalmente dependente do sistema.
Caso de uso típico:
Usar a Paths para pegar um Path. Usar a Files para fazer
algo com um arquivo.
12
12
13. Exemplo prático dos ajudantes do Java
NIO.2
• Cópia de arquivo realmente fácil
– Com ajuste fino
Path src = Paths.get(“/home/fred/readme.txt”);
Path dst = Paths.get(“/home/fred/copy_readme.txt”);
Files.copy(src, dst,
StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING);
• Movimentação do arquivo é suportada
– Movimento atômico opcional é suportado
Path src = Paths.get(“/home/fred/readme.txt”);
Path dst = Paths.get(“/home/fred/readme.1st”);
Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE);
13
13
14. Funcionalidade do Java NIO.2 –
Classe Files
• Classe ajudante Files é uma ótima ferramenta para:
• Copiar
• Criar Diretórios
• Criar arquivos
• Criar Links
• Usar a pasta temporária do sistema
• Deletar
• Atributos – Modificados/Proprietário/Permissões/Tamanho, etc.
• Leitura/Escrita
14
14
15. Pastas com Java NIO.2
• DirectoryStream itera sobre entradas
– Escala para pastas grandes
– Usa menos recursos
– Diminui o tempo de resposta para sistemas de arquivos remotos
– Implementa Iterable e Closeable para prover produtividade
• Suporte a filtragem
– Suporte embutido para glob, expressões regulares e filtros
personalizados.
Path srcPath = Paths.get(“/home/fred/src”);
try (DirectoryStream<Path> dir =
srcPath.newDirectoryStream(“*.java”)) {
for (Path file : dir)
System.out.println(file.getName());
}
15
15
16. Links simbólicos com Java NIO.2
• Path e Files são“conscientes dos links”
Path novoLink = Paths.get(. . .);
Path arquivoExistente = Paths.get(. . .);
try {
Files.createLink(novoLink, arquivoExistente);
} catch (IOException x) {
System.err.println(x);
} catch (UnsupportedOperationException x) {
//Alguns sistemas de arquivos ou configurações
//podem não suportar links
System.err.println(x);
}
16
16
17. Caminhando na
árvore de arquivos com Java NIO.2
• A interface FileVisitor faz a caminhada sobre a árvore de
arquivos para pesquisa ou outras atividades ser trivial
• SimpleFileVisitor implementa
preVisitDirectory(T dir, BasicFileAttributes attrs);
visitFile(T dir, BasicFileAttributes attrs);
visitFileFailed(T dir, IOException exc);
postVisitDirectory(T dir, IOException exc);
AMOSTRA:
Path diretorioInicial = ...;
PrintFiles pf = new PrintFiles(); // SimpleFileVisitor sub
// visitFile(Path p, BasicFileAttributes bfa) {
// System.out.println(file.getFileName());}
Files.walkFileTree(diretorioInicial, pf);
17
17
18. Vigiando um diretório com Java NIO.2
• Crie um observador WatchService para o sistema de
arquivos
• Registre um diretório para o observador
• “Observador” pode ser consultado ou esperar por
eventos
• Eventos criados na forma de chaves (Keys)
• Recuperar a chave (Key) de um Watcher
• A chave tem o nome do arquivo e os eventos dentro dela
para adicionar/remover/atualizar
• Capacidade de detecção de
estouro de eventos
18
18
19. Sistemas de arquivos personalizados
com o NIO.2
• Classe FileSystems é factory para os ótimos FileSystem
(interface)
• Java 7 permite o desenvolvimento de FileSystems
personalizados, por exemplo:
• Baseados em memória ou zip
• Distribuídos e tolerantes a falhas
• Substitutos ou suplementares ao provedor de sistemas de
arquivos padrão
• Dois passos:
• Implementar java.nio.file.spi.FileSystemProvider
• URI, Caching,Manipulação de arquivos, etc.
• Implementar java.nio.file.FileSystem
• Roots, acesso de leitura e escrita, gravação de arquivos, etc.
19
19
20. Provedor de sistema de arquivos
NIO.2 para arquivos zip/jar
Um provedor de sistemas de arquivos totalmente funcional e
suportado no NIO.2 para arquivos zip e jar
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
URI u= URI.create("jar:file:/foo/zipfs/zipfstest.zip");
try (FileSystem z = FileSystems.newFileSystem(u, env)) {
Path externalTxtFile = Paths.get("/foo/zipfs/Sample.txt");
Path pathInZipfile = z.getPath("/Sample.txt");
// copy a file into the zip file
externalTxtFile.copyTo(pathInZipfile);
}
20
20
21. APIs de Concorrência JSR 166y - Phasers
haser
• Barreira similar ao CyclicBarrier e CountDownLatch
• Usado por muitas threads para esperar por em ponto comum
• Por exemplo, uso para criar N Threads que você queira que faça
simultaneamente algo comum – metáfora do “tiro de largada”
• Como o Phaser é um melhoramento?
• Adição/remoção dinâmico de Dynamic add/remove de partes
para serem sincronizadas
• Melhor prevenção de deadlocks
• Contagem de chegada e opções de avanço de fase,etc
• APIs para conclusão
• Hierarquização (Estrutura de árvore)
• Melhor que sincronizar 100 threads sincronizar 2x50
21
21
22. APIs de Concorrência JSR 166y -
TransferQueue
nterface TransferQueue
• Extension para BlockingQueue
• Implementada por LinkedTransferQueue
• Benefícios adicionais:
• Adiciona métodos:
• transfer(E e), tryTransfer(E e),
tryTransfer(E e, long timeout),
hadWaitingConsumer(),
getWaitingConsumerCount()
• Permite que filas mais inteligentes sejam construídas – avança a
estrutura de dados se é conhecido que há consumidores
esperando
22
22
23. Fork Join Framework - JSR 166y - Pools
• ForkJoinPool
– Service para rodar ForkJoinTasks
– aFjp.execute(aTask); // asincr
– aFjp.invoke(aTask); // esperar
– aFjp.submit(aTask); // async + future
– ForkJoinPool(); // padrão para platform
– ForkJoinPool(int n); // # threads concorrentes
– ForJoinPool(n,aThreadFactory,exHandler,FIFOtasks); /
/ Crie seu próprio manipulador de threads,
manipulador de exceções, e boolean na tarefa de
ordenação (por padrão, LIFO)
23
23
24. Fork Join Framework - JSR 166y - Tasks
• ForkJoinTask
– A classe abstrata base para:
• RecursiveAction
– Uma tarefa recursiva resultless
– Implementa método abstrato
compute() para cálculos
• RecursiveTask
– Similar ao RecursiveAction,
mas retorna um resultado
ForkJoinPool p = new ForkJoinPool();
MyTask mt = new MyTask(n); // implementA compute
p.submit(mt);
while (!mt.isDone()) {/*MENTIRA!*/ }
System.out.println(mt.get());
24
24
25. Fork Join Framework - JSR 166y -
compute()
• Exemplo de RecursiveAction para incrementar um array
protected void compute() {
if (hi - lo < THRESHOLD) {
for (int i = lo; i < hi; ++i) array[i]++; }
else {
int mid = (lo + hi) >>> 1;
invokeAll(new IncrementTask(array, lo, mid),
new IncrementTask(array, mid, hi));}
• Exemplo de RecursiveTask example para a sequência de FIbonacci
protected Integer compute() {
if (n <= 1) return n;
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.fork(); f1.fork();
return f2.join() + f1.join();}
25
25
26. Números randômicos concorrentes -
JSR 166y
• Criação de números aleatórios existente torna-se
fonte inconsitente de contenção entre threads em
aplicativos simultâneos
• Esperados melhoramentos de RNG concorrentes
com o advento do Fork Join Framework
• Classe java.util.ThreadLocalRandom
• ThreadLocalRandom.current().nextDouble(…)
• ThreadLocalRandom.current().nextInt (…)
• ThreadLocalRandom.current().nextLong(…)
26
26
27. JSR 166y – Classe ConcurrentLinkedDeque
• Filas duplamente ligadas baseadas em nós
• Como uma Queue, mas permite a remoção de elementos
da frente e de trás
• Inserção concorrente, remove e acessa em múltiplas
threads
• Iterators são fracamente consistentes
27
27
28. Melhoramento no ClassLoader –
prevenção de Deadlock ClassLoaders não eram
Hierarquia de classes: “suficientemente
granulares”e
class A extends B ; class C extends D ; propensos a
Classloader personalizado CL1: deadlock
Carrega diretamente a classe A
delega ao ClassLoader personalizado CL2 p/ classe B Java 7 tem um
Classloader personalizado CL2: “classloader paralelo”
Carrega diretamente a classe C
delega ao ClassLoader personalizado CL1 p/ classe D
Thread 1:
Usa CL1 para carregar a classe A (trava CL1) (in SE 7 – lock CL1+A)
defineClass A inicia loadClass B (tenta travar CL2) (in SE7 – lock CL2+B)
Thread 2:
Usa CL2 para carregar a classe C (trava CL2) (in SE 7 – lock CL2+C)
defineClass C inicia loadClass D (tenta travar CL1) (in SE7 – lock CL1+D)
28
28
29. Melhoramentos no URLClassLoader– close()
// Criar um classLoader a partir do "foo.jar"
URL url = new URL("file:foo.jar");
URLClassLoader loader = new URLClassLoader (new URL[] {url});
Class cl = Class.forName ("Foo", true, loader);
Runnable foo = (Runnable) cl.newInstance();
foo.run();
loader.close ();
// foo.jar é atualizado de alguma forma
loader = new URLClassLoader (new URL[] {url});
cl = Class.forName ("Foo", true, loader);
foo = (Runnable) cl.newInstance();
// Executa a nova implementação de Foo
foo.run();
29
29
30. Unicode 4 -> Unicode 6.0
• Unicode é originalmente de 16 bit
• 16 bits não é o suficiente para o Unicode 6, mas a
retrocompatibilidade deve ser mantida
• Usar String “U+hex” para expressar caracter em Unicode
• Unicode 6.0 adiciona milhares de caracteres
• Suporte para propriedade e arquivos de dados (interessante
principalmente para glifos japoneses e scripts indi)
• Suporte completo a expressões regulares com Unicode 6.0!
30
30
31. Códigos de moeda extensível (ISO 4217)
• ISO 4217 define códigos de moedas
• Possibilidade de substituir a moeda padrão no
arquivo
<JAVA_HOME>/lib/currency.properties
permite apoiar mudanças globais sem atualizar o
Java
• Formato: Código do país ISO 3166 = Código da ISO
4217
# Exemplo do canada adotando dólar americano
# CA=CAD,124,2 é o código padrão da ISO 4217
CA=USD,840,2
31
31
32. Melhorias no Number Shaper
• NumericShaper usado para mapear números para codificações não-
Latin (desde o 1.4)
• NumericShaper tradicionalmente usado como uma máscara de bits
inteiros para o padrão
• Bom quando havia somente 19 padrões
• No Java 7 temos 34 (> 32 bits!!)
• Java 7 agora tem Enum NumericShaper.Range
• Retrocompatibilidade mantida, novas APIs adicionadas para o uso de
Enum quando solicitado
32
32
33. Melhoramento do Locale – Categorias
• Locale padrão pode ser modificado independentemente
para formato de recursos (datas, números, moedas) e
recursos de tela (menus e caixas de diálogo)
• Pode exemplo, uma aplicação para público japonês que
lidam com transações financeiras dos EUA pode:
//Enum Locale.Category – DISPLAY e FORMATO
//Padrão sem arg get/set é DISPLAY
Locale.setDefault(DISPLAY, Locale.JAPAN);
Locale.setDefault(FORMAT, Locale.US);
33
33
34. Melhoramento do Locale– BCP 47 Extensions
• Java 7 confirms a IETF BCP 47 (ref UTS #35)
• Especifica as extensões de uma Locale (get/set)
• Ex: de-DE-co-phonebk
• Nenhuma garantia que a plataforma realmente estará
nessa extensão
Chave Descrição Exemplo Descrição do exemplo
calendar
ca ca-buddhist Calendário budista tailandês
algorithm
co agrupamento co-pinyin Ordenação Pinyin para o Latino
parametros do
k* kf-upper Donald antes do donald
agrupamento
cu Tipo da moeda cu-usd Dólar americano
nu Padrão numérico nu-jpanfin Números financeiros japoneses
tz Fuso tz-aldav Europa/Andorra
Tipo de variante
va va-posix Estilo de localidade POSIX
comum 34
34
35. Look and Feel Nimbus
• Look-and-feel multiplataforma melhor que o Metal;
• Introduzido no Java SE 6u10, agora parte do Swing
• Não é o L&F padrão
• Implementação escalável Java 2D
• Scalable Java 2D impl
35
35
36. Componente Jlayer
Fácil enriquecimento de componentes Swing
//Coloque seu componente dentro de um JLayer
JLayer<JPanel> layer = new JLayer<JPanel>(panel);
//Interface customizada provê todas funcionalidades extras
layer.setUI(myLayerUI);
// adicionar a interface como um componente comum
frame.add(layer);
36
36
37. Mistura de AWT e Swing – Funciona*
• Na 6u12 e 7u1, há algumas ressalvas para barras de rolagem
37
37
38. Janelas translúcidas
• API privada adicionada na 6u10, agora público no Java 7
• Suporte (baseado na plataforma) para:
• Translucidez uniforme;
• Translucidez por pixel
• Transparência por pixel
// Uniforme e simples:
aWindow.setOpacity(0.5f);
// Por pixel g2d é a g2d de um Jpanel sobre o paintComponent(g)
Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B,0),
0.0f, getHeight(), new Color(R, G, B, 255), true);
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
38
38
39. Renderização Java 2D baseada no
Xrender para o X11 moderno
• Performance gráfica melhorada.
• Desligada por padrão (compatibilidade com versões
anteriores)
• Tranquilo:
-Dsun.java2d.xrender=true
• Verboso (log na saída padrão para sucesso ou fracasso)
-Dsun.java2d.xrender=True
39
39
40. Fontes OpenType/CFF
• Plataforma Java precisa suportar fontes TrueType,
outras tecnologias de fonte são dependentes de
implementação
• Java 7 adiciona suporte para “Compact Font Format”
- OpenType/CFF.
40
40
41. Melhor suporte para as fontes do Linux
• Cinco fontes desde o Java 1.0:
• Serif, Sans-serif, Monospaced, Dialog e
DialogInput
• Deve mapear a fonte física no seu sistema
• Sem consistência em fontes no Linux
• É necessário editar fontconfig.properties
• Java 7 no Linux (e Solaris 11) usa a
“libfontconfig” do sistema, refletindo o que
as aplicações Desktop Gnome/KDE
utilizam
41
41
43. JDBC 4.1
• “Try-with-resources” automaticamente fecha recursos dos tipos
Connection, ResultSet e Statement
try (Statement stmt = con.createStatement()) { // ... }
• RowSet 1.1 introduz RowSetFactory e RowSetProvider
/*Factory com opções determinadas na linha de comando ou
metainf */
myRowSetFactory = RowSetProvider.newFactory();
jdbcRs = myRowSetFactory.createJdbcRowSet();
jdbcRs.setUrl("jdbc:myDriver:myAttribute"); //etc
jdbcRs.setCommand("select CAF_NAME, SUP_ID, PRECO,
VENDAS, TOTAL from CAFES");
jdbcRs.execute();
43
43
44. Java DB Enhancements (Derby)
• JDK 7 inclui Java DB 10.8.1.2
• Novidades desde o JDK 6
• Tipo de dados BOOLEAN
• Truncamento de tabelas
• Navegação em Query plans
• Cálculo automático das estatísticas dos índices
• Nomes de banco de dados em Unicode
• Tratamento de interrupções melhorado
• Agora pode interromper threads de conexão
• Otimização MAX (Mais rápido!)
44
44
45. Incorporação do arquivo JNLP na tag
do Applet
• Economiza uma requisição na rede quando o applet é
carregado na primeira vez
• Base64 codifica o conteúdo do JNLP em uma chamada
Javascript:
<script
src="http://www.java.com/js/deployJava.js"></script>
<script>
var attributes = {} ;
<!-- Base64 encoded string trunc’d below for readability --
> var parameters = {jnlp_href: 'dynamictree-applet.jnlp',
jnlp_embedded: 'PCEtLSAKLyoKICogQ29weX ... HA+Cg==' } ;
deployJava.runApplet(attributes, parameters, '1.7');
</script>
45
45
46. Capacidade de detectar o estado de inicialização
de um applet no seu carregamento
<script> function onLoadHandler(){
function registerAppletStateHandler() { document.
switch (drawApplet.status) { getElementById("mydiv“)
case 1: <!–- applet is loading --> .innerHTML =
drawApplet.onLoad = onLoadHandler; "Applet has loaded";
case 2: <!–- applet is loaded --> draw();
case 3: <!–- error --> }
document.getElementById("mydiv")
.innerHTML =“No need to onload";
}
<!–- assume java.com/js/deployJava.js is loaded ->
}
var parameters = {java_status_events: 'true'};
<!–- set other params like jnlp->
deployJava.runApplet(attributes, parameters, '1.7');
...
</script>
46
46
47. “Decoração arrastável” do Applet
• Aspectos gráficos do Applet se aplicam igualitariamente
nas execuções dentro e fora do browser – sem bordas,
etc.
47
47
48. Outra variedade de coisas do JNLP
que são novidades…
• JNLP parcialmente assinado
• Simplifica o build e implantação em alguns cenários
• Arquivo JNLP externo pode diferir de um
• Arquivo JNLP externo pode diferir de um recurso embutido
no jar
• Direcionamento de recursos para uma versão de SO
<resources os="Windows Vista Windows 7">
<jar href=“legacySound.jar"/> </resources>
• Melhores “preferências de instalação de aplicações
• Por exemplo, atributo para determinar se a aplicação
aparecerá no painel de “Adicionar ou remover programas”
48
48
49. Máquina virtual: Atualização para um
GC experimental – G1
• Garbage First - “G1” destinado a substituir*
Concurrent Mark-Sweep (CMS) na Hotspot em um
release próximo
• G1 está incluído para experimentação no Java 7
• Principais benefícios:
• Mais previsibilidade “soft real-time” – configuração temporal
• Alta taxa de transferência (Throughput);
• Básico:
• Heap particionado em regiões de mesmo tamanho
• Compacto como procede – olha para regiões sem objetos
alocados para recuperação imediata
*não é uma declaração oficial para o futuro
49
49
50. VM: Compilação em camadas
• Hotspot tem 2 “cliente” and “servidor” do JIT
• Cliente inicia rapidamente, mas deixa algumas otimizações
– melhor para clientes
• Servidor
• Servidor inicia mais devagar, mas provê melhores
otimizações
• Java 7 adiciona Compilação em camadas
• Trabalhe com JIT primeiro no cliente e, se tivercom bom
código, recompile com o servidor
• Estava aí já há algum tempo,mas sem uma boa
implementação
-server -XX:+TieredCompilation
Imagem de Rémi Forax showing the DaCapo Jython benchmark.
http://www.java.net/blogs/forax
50
50
51. VM: OOPS Comprimida por padrão
• A ida de sistemas 32bit para 64bit vai aumentar o heap
em ~1.5x simplesmente por causa de maiores ponteiros
de objetos
• Memória é barata, mas largura de banda e cache não
• OOPS comprimida:
• Ponteiros gerenciados de 32 bits (tamanho de heap similar para
aplicações 32/64 bit)
• Scaled (8 x 4GB pedações) adicionados a base
64 bit
• Útil para heaps maiores que 32 GB
• Compressed OOPS vai ser desligado quando
–Xmx > 32g
51
51
52. VM: invokedynamic ilustrada
this[method_name](x, y)
invokedynamic
[#bootstrapMethod]
.this_method_name 1. Invoca bootstrap
class LangaugeRuntime {
2. Produz bootstrapMethod(info) {
CallSite ...
3. Linkagem
completa return new CallSite();
}
CallSite
class AClass {
aMethod(x, y) {
4. Invoca a Method ...
implementação do Handle }
códigio
52
52
53. Melhoramentos na tecnologia Java
XML
• JAXP 1.4.5
• Resoluções de bug e melhoramentos de performance
• JAX-WS 2.2.4
• Resoluções de bug e melhoramentos de performance
• JAXB 2.2.3
• Resoluções de bug e melhoramentos de performance
53
53
54. Elliptic Curve Cryptography (ECC)
• Novo provider nativo adicionado ao JDK7
• Algoritmos baseados no ECC (ECDSA/ECDH)
• Permite extensão de Java Secure Sockets Extension
(JSSE)baseados no ECC
• Comparado a criptografia tradicional, sistemas como
RSA, ECC oferecem segurança equivalente:
• Com tamanhos menores
• Com tamanhos de chave menores
• Computacões mais rápidas
• Pouco poder de consumo
• Economia de memória e banda
54
54
55. Atualizações no Transport Layer
Security (TLS)
• Suporte ao TLS 1.1
• Proteção contra ataques encadeados
• Suporte a TLS 1.2
• Renegociação TLS
• CertPath e TLS algorithm incapacitante
• Pode negar algoritmos específicos no processamento de
caminho e handshaking
55
55
56. Melhoramentos do JavaDoc no Java 7
• Section 508 com guia de acessibilidade
• Legendas, títulos,etc
• Anteriormente, Javadoc era escrito em um OuputStream ao mesmo
tempo que o documento era construído sequencialmente, impondo
limitações
• Agora usa classes internas da “HTMLTree”
• Gera código em conformidade com HTML
• Permite mais avanços no futuro
• Remove limitações de só ser capaz de executar uma vez em qualquer
máquina virtual
• Era bom quando executado como uma ferramenta de linha de
comando
• Integração contínua,etc, gerou a necessidade de se preocupar com
isso
56
56
58. The preceding is intended to outline our general
product direction. It is intended for information
purposes only, and may not be incorporated into any
contract. It is not a commitment to deliver any
material, code, or functionality, and should not be
relied upon in making purchasing decisions.
The development, release, and timing of any
features or functionality described for Oracle’s
products remains at the sole discretion of Oracle.
58
58
59. O r ao
bigd!
Stephen Chin
stephen.chin@oracle.com
tweet: @steveonjava
Desconto especial de 40% para o
JustJava. Entre em apress.com e
digite o código PJVF73
59
59 59
Hinweis der Redaktion
55 minutes – 55 slides Ignite Format No stopping! No going back! Questions? Sure, but only if and until time remains on slide (otherwise, save for later) The PRD for Java 7 had almost 2000 changes, here are 55 of the more relevant ones… 6/27/11
6/27/11 Finally we have support for binary literals.
6/27/11 Support for underscores, that allow you to group together, and make it easier to read the literals.
6/27/11 This show the monthNameToDays method using the JDK 7, where you can use the string in the switch statement, making your code, smaller, clearer, and easier to read.
6/27/11 JDK 7 introduce a solution for the issues presented in the previous slides, the automatic resource management. Now you don't have to worry about closing your resources, they will be automatically closed whe the try block finish execution. Please note the new definition of the try block, where you include the resources to be managed. New superinterface java.lang.AutoCloseable All AutoCloseable (throws Exception) and by extension java.io.Closeable (throws IOException) types useable with try-with-resources Anything with a void close() method is a candidate JDBC 4.1 retrofitted as AutoCloseable too
With automatic resource management even though there are potentially several levels of nesting for the finally clauses that are not immediately visible the full trace of the exceptions that were thrown will be reported. 6/27/11
6/27/11 Now with JDK 7 you can group under the same catch, several exceptions using the “|' operand. Simpler, cleaner and you can reuse common code.
Prior to Java 7, this code would not compile, the types in throws would have to match the types in catch – foo would have to “ throws Exception ” Java 7 adds support for this as long as try block calls all the exceptions in the throws clause, that the variable in the catch clause is the variable that is rethrown and the exceptions are not caught by another catch block. 6/27/11
6/27/11 JDK 7 introduce the diamond operator, now you only need to specify once the type of elements been hold by the collection, on the left hand side, the rest is taking care for you, as java will “infer” the type that will go on the right hand side. This is more complex than just having the compiler perform string substitution. For certain cases the type to be inserted is not represented by the string in the variable declaration (wildcards are a good example). The compiler must infer the type parameter for the instantiation from the type parameter of the variable declaration. List<? extends A> la; la = new ArrayList<B>(); la = new ArrayList<C>(); la = new ArrayList<D>(); List<? super B> lb; lb = new ArrayList<A>(); //fine lb = new ArrayList<C>(); //will not compile public void someMethod(List<? extends B> lb) { B b = lb.get(0); // is fine lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B } public void otherMethod(List<? super B> lb) { B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A lb.add(new B()); // is fine, as we know that it will be a super type of A }
Lets study this code closely as we get an unchecked generic array warning. There is a heavy use of the static method asList from the Arrays class, defined as: public static <T> List<T> asList(T... a) Returns a fixed-size list backed by the specified array. Lets go back to the code. We are defining monthsInTwoLanguages, and we are expecting it to be a List<List<String>>. First we call Arrays.asList(&quot;January&quot;, &quot;February&quot;), this will return a List<Strings>, in other words a list with the months in English. Then we call Arrays.asList(&quot;Gennaio&quot;, &quot;Febbraio&quot; )); and again we will get a List<Strings>, in this case it will be a list with the months in Italian. Then we call Arrays.asList(Arrays.asList(&quot;January&quot;, &quot;February&quot;), Arrays.asList(&quot;Gennaio&quot;, &quot;Febbraio&quot; )); in this case the call seems to be Arrays.asList( List<String>, List<String>) , from previous paragraph. Then we expect to get as result a List<List <String>> that is the expected type for our definition, so why are we getting this warning? When a generic type is instantiated in java, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. This is done to maintain binary compatibility with Java libraries and applications that were created before generics. Then when we do the first asList call, the only stored information is List, we don't store any information about String, the type of elements hold by this list. And it's the same scenario for the second asList call. When we finally get to the 3 rd asList call, know we are returning a new List <List <???>> but we didn't store any information about String, so the compiler doesn't know what ??? means, In our case we are sure that we have String types, but because we don't have any information about it, it could be wrong, the compiler doesn't have this information, and that's the reason why we get the warning. There could be a potential issue. 6/27/11
6/27/11 Three key new helper Types new in Java 7 Class java.nio.file.Files Exclusively static methods to operate on files, directories and other types of files Class java.nio.file.Paths Exclusively static methods to return a Path by converting a string or Uniform Resource Identifier (URI) Interface java.nio.file.Path Used for objects that represent the location of a file in a file system, typically system dependent. Typical use case: Use Paths to get a Path. Use Files to do stuff. From a developer’s perspective the biggest change will be to replace use of the File object with the Path object. Since File was not designed to be extended it was not possible to add functionality so a new class was required. In many places this can be used in exactly the same way, but there are a few differences that developers will need to be aware of to use this correctly. In the existing IO API reading the contents of a directory blocks until all entries have been retrieved. If you are reading several millin file names across a network connection (not unusual today) this can take a very longh time. NIO2 now provides support for streaming entries so they can be processed as they arrive. There is also support for filtering as part of the API so that it is easy to list only certin types of file and so on. Symbolic link support is optional and is based on the long standing UNIX semantics. Most of the time the link is treated as a normal file, exceptions to this include the delete operation and WalkFIleTree (although the FOLLOW_LINKS option can be used with this). To provide extensibility the Filesystem class provides an interface to a Filesystem which can be any form of file storage system, for example a ZIP file can be accessed as if it were a filesystem even though it is itself a file on another filesystem. The attribute package provides enhanced access to metadata for files and also solves a longstanding performance problem, namely that every request for an attribute results in a separate stat() call
File copy is really easy With fine grain control File move is supported Optional atomic move supported Finally the most obvious file system operations are supported in a clean consistent way in Java. Copying, moving and renaming files is all performed using a Path for each part of the operation. Three copy options can also be specified to copy the attributes of the file rather than using the defaults, to replace an existing file if one already exists at the destination path and to make the move an atomic operation from the filesystem perspective. The Files class provides a large number of utility methods for typical filesystem operations (copy, move, delete, createDirectory and so on).
Files helper class is feature rich: Copy Create Directories Create Files Create Links Use of system “temp” directory Delete Attributes – Modified/Owner/Permissions/Size, etc. Read/Write 6/27/11
DirectoryStream iterate over entries Scales to large directories Uses less resources Smooth out response time for remote file systems Implements Iterable and Closeable for productivity Filtering support Build-in support for glob, regex and custom filters The DirectoryStream class provides an iterator that can be used to read entries from a directory. One point of note is that, as the DirectoryStream provides an Iterator, it is not possible to use the DirectoryStream more than once, since there is no way to reset an Iterator,. There is built in support for regular expressions so complex patterns can be used like *.{c,h,cpp,hpp,java}
Java NIO.2 Symbolic Links Path and Files are “link aware”
Java NIO.2 Walking A File Tree A FileVisitor interface makes walking a file tree for search, or performing actions, trivial. SimpleFileVisitor implements
Java NIO.2 Watching A Directory Create a WatchService “watcher” for the filesystem Register a directory with the watcher “ Watcher” can be polled or waited on for events Events raised in the form of Keys Retrieve the Key from the Watcher Key has filename and events within it for create/delete/modify Ability to detect event overflows
NIO.2 Custom FileSystems FileSystems class is factory to great FileSystem (interface) Java 7 allows for developing custom FileSystems, for example: Memory based or zip file based systems Fault tolerant distributed file systems Replacing or supplementing the default file system provider Two steps: Implement java.nio.file.spi.FileSystemProvider - URI, Caching, File Handling, etc. Implement java.nio.file.FileSystem - Roots, RW access, file store, etc. 6/27/11
NIO.2 filesystem provider for zip/jar archives A fully-functional and supported NIO.2 filesystem provider for zip and jar files 6/27/11
6/27/11 Phaser Barrier similar to CyclicBarrier and CountDownLatch Used for many threads to wait at common barrier point For example, use this to create N threads that you want to do something simultaneously – “ start gun ” metaphore How is Phaser an improvement? Dynamic add/remove “parties” to be sync’d Better deadlock avoidance Arrival “ counting ” and phase advance options, etc Termination api’s Tiering (tree structure) Rather than sync 100 threads, sync 2x50 then 2x. Java SE 7 includes updates to the concurrency APIs first introduced in Java SE 5. This is an update to an update;the orinial utilities were defined in JSR166. This was eXtended in JSR166x (Java SE 6) and extended further through JSR166y (Java SE 7). Introduces the fork-join framework for fine grained parallelism The Phaser which is a reusable synchronization barrier, similar in functionality to CyclicBarrier and CountDownLatch but supporting more flexible usage.
6/27/11 TransferQueue interface Extension to BlockingQueue Implemented by LinkedTransferQueue Additional Benefits: Adds methods: transfer(E e), tryTransfer(E e), tryTransfer(E e, long timeout), hadWaitingConsumer(), getWaitingConsumerCount() Allows for smarter queues to be built – sidestep the data structure if it ’ s known there are consumers waiting. A TransferQueue is a BlockingQueue in which producers may wait for consumers to receive elements. A TransferQueue may be useful for example in message passing applications in which producers sometimes (using method transfer(E)) await receipt of elements by consumers invoking take or poll, while at other times enqueue elements (via method put) without waiting for receipt. Non-blocking and time-out versions of tryTransfer are also available. A TransferQueue may also be queried, via hasWaitingConsumer(), whether there are any threads waiting for items, which is a converse analogy to a peek operation. Like other blocking queues, a TransferQueue may be capacity bounded. If so, an attempted transfer operation may initially block waiting for available space, and/or subsequently block waiting for reception by a consumer. Note that in a queue with zero capacity, such as SynchronousQueue, put and transfer are effectively synonymous. This is implemented by the LinkedTransferQuue which is an unbounded TransferQueue based on linked nodes. This queue orders elements FIFO (first-in-first-out) with respect to any given producer. The head of the queue is that element that has been on the queue the longest time for some producer. The tail of the queue is that element that has been on the queue the shortest time for some producer.
ForkJoinPool Service for running ForkJoinTasks aFjp.execute(aTask); // async aFjp.invoke(aTask); // wait aFjp.submit(aTask); // async + future ForkJoinPool(); // default to platform ForkJoinPool(int n); // # concurrent threads ForJoinPool(n,aThreadFactory,exHandler,FIFOtasks); // Create your own thread handler, exception handler, and boolean on task ordering (default LIFO) The main classes for the Fork Join framework: ForkJoinPool – Creates a pool of worker threads to execute the tasks.
ForkJoinTask The abstract base class for: RecursiveAction A recursive resultless task Implements compute() abstract method to perform calculation RecursiveTask Similar to RecursiveAction but returns a result The main classes for the Fork Join framework: ForkJoinTask – a task to be processed
RecursiveAction example to increment an entire array protected void compute() { if (hi - lo < THRESHOLD) { for (int i = lo; i < hi; ++i) array[i]++; } else { int mid = (lo + hi) >>> 1; invokeAll(new IncrementTask(array, lo, mid), new IncrementTask(array, mid, hi));} RecursiveTask example for Fibonacci numbers protected Integer compute() { if (n <= 1) return n; Fibonacci f1 = new Fibonacci(n - 1); Fibonacci f2 = new Fibonacci(n - 2); f1.fork(); f1.fork(); return f2.join() + f1.join();} The main classes for the Fork Join framework: RecursiveAction – A recursively decomposable task that does not return a result RecursiveTask – A recursively decomposable task that does return a value
Concurrent Random Numbers - JSR 166y Existing RNG becomes unwitting source of contention between threads in concurrent apps Expected more needs of concurrent RNG with advent of Fork Join Framework 6/27/11
JSR 166y – ConcurrentLinkedDeque Class Unbound concurrent deque based on linked nodes Like a Queue, but allows front and rear removal of elements Concurrent insert, remove and access on multiple threads Iterators are weakly consistent 6/27/11
ClassLoader Improvements – Deadlock Avoidance Class Hierarchy: class A extends B ; class C extends D ; Custom Classloader CL1: directly loads class A delegates to custom ClassLoader CL2 for class B Custom Classloader CL2: directly loads class C delegates to custom ClassLoader CL1 for class D Thread 1: Use CL1 to load class A (locks CL1) defineClass A triggers loadClass B (try to lock CL2) Thread 2: Use CL2 to load class C (locks CL2) defineClass C triggers loadClass D (try to lock CL1) ClassLoaders were “ not sufficiently granular ” and prone to deadlock Java 7 has a “ parallel capable classloader ” (in SE 7 – lock CL1+A) (in SE7 – lock CL2+B) (in SE 7 – lock CL2+C) (in SE7 – lock CL1+D) 6/27/11
URLClassLoader Improvements – close() // create a class loader loading from &quot;foo.jar&quot; URL url = new URL(&quot;file:foo.jar&quot;); URLClassLoader loader = new URLClassLoader (new URL[] {url}); Class cl = Class.forName (&quot;Foo&quot;, true, loader); Runnable foo = (Runnable) cl.newInstance(); foo.run(); loader.close (); // foo.jar gets updated somehow loader = new URLClassLoader (new URL[] {url}); cl = Class.forName (&quot;Foo&quot;, true, loader); foo = (Runnable) cl.newInstance(); // run the new implementation of Foo foo.run(); 6/27/11
Unicode 4 -> Unicode 6.0 Unicode standard was originally 16 bit 16 bits not sufficient for Unicode 6, but backward compatibility needs to be maintained Use String “ U+hex ” to express char in Unicode Unicode 6.0 adds thousands of new characters Support for properties and data files (mostly interesting to Japanese Telcos and Indic scripts) Full Unicode 6.0 REGEX support! 6/27/11
Extensible Currency Codes (ISO 4217) ISO 4217 Defines Currency Codes Possible to supersede default currencies with <JAVA_HOME>/lib/currency.properties file Allows for supporting global changes without updating Java Format: ISO 3166 Country code = ISO 4217 Codes # Sample currency property if Canada adopts USD # CA=CAD,124,2 is default ISO 4217 code CA=USD,840,2 6/27/11
Number Shaper Enhancements NumericShaper used to map numbers to non Latin char sets (since 1.4) NumericShaper traditionally used an int bitmask for defaults Fine when there were only 19 defaults In Java 7 there are 34 (> 32 bits!!) Java 7 now has an Enum NumericShaper.Range Backward compatibility maintained, new API’s added for Enum use where desired 6/27/11
Locale enhancement – Categories Default Locale can be set independently for format resources (dates, numbers, currencies) and display resources (menus and dialogs) For example, an application for Japanese speakers who deal with US financial transactions may: //Enum Locale.Category – DISPLAY and FORMAT //Default no arg get/set is DISPLAY Locale.setDefault(DISPLAY, Locale.JAPAN); Locale.setDefault(FORMAT, Locale.US); 6/27/11
Locale enhancement – BCP 47 Extensions Java 7 confirms to IETF BCP 47 (refs UTS #35) Specify extensions to a Locale (get/set) i.e., de-DE-co-phonebk No guarantee the underlying platform can honour extension 6/27/11
6/27/11 Better than Metal for cross platform look-and-feel Introduced in Java SE 6u10, now part of Swing Not the default L&F Scalable Java 2D impl The Nimbus look and feel was introduced in Java SE 6 update 10 as a replacement for the metal cross platform L&F. In Java SE 7 this has been moved to a standard part of the platform (previously it was an oracle extension package, now it is in the javax.swing.plaf package). The decision was made not to make this the default L&F, this will continue to be Metal. Although many people in the community wanted this it was decided that the impact on existing applications would be too great.
6/27/11 The Jlayer component provides an easy way to add an overlay to existing Swing components. Examples are a progress wheel or highlighting only vallid choices in a multiple-choice component.
Mixing of AWT and Swing – Works* As of 6u12 and 7u1, some caveats for scroll bars 6/27/11
Translucent Windows Private API added in 6u10, made public in Java 7 Support (based on platform) for: Uniform Translucency Per Pixel Translucency Per Pixel Transparency // simple uniform: aWindow.setOpacity(0.5f); // Per pixel g2d is the g2d of a Jpanel on paintComponent(g) Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B,0), 0.0f, getHeight(), new Color(R, G, B, 255), true); g2d.setPaint(p); g2d.fillRect(0, 0, getWidth(), getHeight()); 6/27/11
Xrender-based Java 2D for modern X11 Improved Graphics Performance Off by default (backward compatibility) Quiet: -Dsun.java2d.xrender=true Verbose (log on stdout if successful or not) -Dsun.java2d.xrender=True 6/27/11
OpenType/CFF Fonts Java Platform must support TrueType fonts, other font technologies is implementation dependent Java 7 adds support for “ Compact Font Format ” - OpenType/CFF. 6/27/11
Better Support for Linux Fonts Five logical fonts since Java 1.0: Serif, Sans-serif, Monospaced, Dialog, and DialogInput Must map to physical font on your system No consistency in fonts in Linux Required editing fontconfig.properties Java 7 on Linux (and Solaris 11) uses system “ libfontconfig ” , reflecting what Gnome/KDE desktop applications use 6/27/11
HSV/HSL Tab on JColorChooser Class 6/27/11
Try-with-resources statement to automatically close resources of type Connection , ResultSet , and Statement try (Statement stmt = con.createStatement()) { // ... } RowSet 1.1 introduces RowSetFactory and RowSetProvider //Factory options (impl) set on cmd line or metainf myRowSetFactory = RowSetProvider.newFactory(); jdbcRs = myRowSetFactory.createJdbcRowSet(); jdbcRs.setUrl(&quot;jdbc:myDriver:myAttribute&quot;); //etc jdbcRs.setCommand(&quot;select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES&quot;); jdbcRs.execute(); 6/27/11
JDK 7 includes Java DB 10.8.1.2 New Since JDK 6 BOOLEAN data type Table truncation Query plan browsing Automatic calc of index stats Unicode database names Improved interrupt handling Can now interrupt connection threads MAX optimization (faster!) XML operator portability 6/27/11
Embedding JNLP File in Applet Tag Saves a network round trip first time applet is loaded Base64 Encode the JNLP contents into a Javascript call: <script src=&quot;http://www.java.com/js/deployJava.js&quot;></script> <script> var attributes = {} ; <!-- Base64 encoded string trunc’d below for readability --> var parameters = {jnlp_href: 'dynamictree-applet.jnlp', jnlp_embedded: 'PCEtLSAKLyoKICogQ29weX ... HA+Cg==' } ; deployJava.runApplet(attributes, parameters, '1.7'); </script> 6/27/11
Ability to detect applet init status on load 6/27/11
Draggable Applet Decoration Applet decoration settings apply equally to in browser and out of browser launches – borderless, etc. 6/27/11
Other Misc New JNLP Stuff... Partially signed JNLP Simplifies build and deployment in some scenarios External JNLP file may differ from one embedded in jar Targeting resources to particular version of OS <resources os=&quot;Windows\\ Vista Windows\\ 7&quot;> <jar href= “ legacySound.jar&quot;/> </resources> Better “ install ” preferences of an application For example, attribute to determine if app appears on “ Add or Remove Programs panel ” 6/27/11
VM: Updates to Experimental GC – G1 Garbage First - “ G1 ” intended to replace* Concurrent Mark-Sweep (CMS) in Hotspot at some future release G1 is included for experimentation in Java 7 Key benefits: More predictably “ soft real-time ” – temporal configuration High throughput Basics: Heap partitioned into equal-sized heap regions Compacts as it proceeds – looks for regions with no live objects for immediate reclamation *not an official fwd looking statement 6/27/11
VM: Tiered Compilation Hotspot has 2 JIT ’ s “ client ” and “ server ” Client starts fast, but let optimizations – best for clients Server starts slower, but provides better optimizations Java 7 adds Tiered Compiliation JIT the code first with “ client ” , and if it ’ s really hot code, recompile with “ server ” Has been around for a while, but not with a great implementation -server -XX:+TieredCompilation Image from Rémi Forax showing the DaCapo Jython benchmark. http://www.java.net/blogs/forax 6/27/11
VM: Compressed OOPS by default Going from 32bit to 64bit system will grow the heap by ~1.5x simply because of bigger ordinary object pointers Memory is cheap, but bandwidth and cache is not Compressed OOPS: Managed 32 bit pointers (similar heap sizes for 32/64 bit apps) Scaled (8 x 4GB chunks) added to a 64 bit base Useful for heaps up to 32GB Compressed OOPS will turn off when –Xmx > 32g 6/27/11
To help understand this we provide a diagram. To shorten this presentation you may want to remove the details of how invokedynamic works as this does not impact on most developers.
6/27/11 Java XML Technology Enhancements JAXP 1.4.5 Bug fixes and performance improvements JAX-WS 2.2.4 Bug fixes and performance improvements JAXB 2.2.3 Bug fixes and performance improvements Here are a few miscellaneous things that don’t fit into the preceeding areas. Some minor changes to cryptography in terms of the underlying algorithm used. Various updates to Java APIs defined in other JSRs Some minor changes to class loading which will only have an impact on a very small number of developers. Finally! Javadocs get CSS support so we can bring javadocs into the 21 st Century.
New Native Provider added to JDK 7 ECC-based algorithms (ECDSA/ECDH) Enables ECC based Java Secure Sockets Extension (JSSE) Compared to traditional crypto systems like RSA, ECC offers equivalent security: With smaller key sizes Faster computations Lower power consumption Memory and bandwidth savings 6/27/11
Transport Layer Security (TLS) Updates Support for TLS 1.1 Protection against cipher block chaining attacks Support for TLS 1.2 TLS Renegotiation CertPath and TLS algorithm disabling Can deny specific algorithms in path processing and handshaking, i.e., MD2 6/27/11
JavaDoc Improvements in Java 7 Section 508 accessibility guidelines Captions, headings, etc. Previously, JavaDoc wrote to an OutputStream on the fly meaning it built the document sequentially, imposing limitations Now uses internal “ HTMLTree ” classes Generates compliant HTML Allows for more advancements in the future Removes limitation of only being able to execute only once in any VM Was fine when used as a command line tool Continuous build, etc, made it necessary to address this! 6/27/11
CSS for JavaDoc - stylesheet.css 6/27/11
6/27/11 This is the standard Oracle safe-harbour statement. Please allow the audience to read this in their own time.