Escolar Documentos
Profissional Documentos
Cultura Documentos
lucabastos@gmail.com
java.nio - Agenda
Introduo
Buffers
Channels
Scatter/Gather
File Channels e file locking
Memory mapped files
Transferncia channel to channel
Socket Channels
Selectors e SelectionKeys
Comparao entre java.io e java.nio
java.nio - Introduo
Alm disto algumas decises tomadas no desenvolvimento
inviabilizam o uso destas APIs Java em aplicaes que exigem IO
de alta performance.
Abstrao distante das facilidades do SO;
Locks demais sem controle do desenvolvedor;
Falta de file locking;
Falta de buffers em algumas classes;
IO sempre bloqueante;
java.nio - Introduo, problemas java.io
As classes do java.io e java.net, no caso de uso das Streams,
movem os dados em pequenos pedaos para facilitar o
programador. Isto significa que as classes de IO do tipo Stream
do Java perdem tempo empacotando e desempacotando bytes
para se ajustar as necessidades do SO. Esta perda ocorre em
todas as composies das Streams.
A classe RandomAccessFile de java.io a nica capaz de
transferir grandes pacotes de dados. Mas no tem buffers.
java.nio - Introduo, problemas java.io
Problema dos StringBuffers
Todos os mtodos pblicos so synchronized. O Java implementa
o operador de concatenao de Strings usando StringBuffer.
Avaliar a expresso "Java" + "NIO" significa fazer:
new StringBuffer.append("Java").append.("NIO").toString()
Problemas do IO Stream
As classes Stream servem para IO byte a byte e as classes
Reader/Writer para o IO de caracteres Unicode. Normalmente
usamos composio. Ler uma seqncia de inteiros a partir de
um arquivo compor um FileInputStream com um
BufferedInputStream e um DataInputStream.
Vrias classes de java.io so synchronized. O mtodo read de
BufferedInputStream synchronized (assim como o write de
BufferedOutputStream). No se pode optar por no fazer locks e
garantir a segurana lendo tudo em uma nica thread.
Quase todos os mtodos de DataOutputStream escrevem um byte
de cada vez, writeLong faz 8 operaes de write. Uma simples
chamada acarreta 8 aquisies de lock.
java.nio - Introduo, problemas java.io
IO sempre bloqueante
O programador Java j se acostumou a criar novas threads
quando quer esperar o resultado de uma operao de IO que
bloqueia enquanto no terminarem os dados. A maioria dos SO
permite colocar as Streams em modo no bloqueante.
java.nio - Introduo, problemas java.io
Os SOs permitem ao desenvolvedor multiplexar muitas Streams
ativas no mesmo trecho de cdigo e em uma nica thread. Usando
s java.io e java.net no se tem isto que usado com sucesso em
alguns servidores web tal como mostra a figura a seguir.
Na figura, o eixo horizontal mostra nmero de usurios e na vertical
o nmero de hits por segundo. Os 4 servidores com melhor
desempenho usam IO no bloqueante e system call select()
(equivalente ao Selector do java.nio). Em verde o Apache 1.3.
java.nio - Introduo, problemas java.io
Fonte: http://www.acme.com/software/thttpd/benchmarks.html
java.nio - Introduo
API java.nio
As APIs disponveis no Java antes da verso 1.4 no permitiam o
desenvolvimento de aplicaes servidoras com desempenho
comparvel s mesmas aplicaes desenvolvidas em outras
linguagens.
A API java.nio includa na verso 1.4 introduz novas abstraes
para fazer IO e desta vez focadas em uma maior aproximao
com o SO. Fornecem classes de gerenciamento dos buffers,
melhoram as classes de IO em rede e arquivos usando facilidades
como selectors e channels e ainda incluem suporte a expresses
regulares e Character sets.
Apresentaremos somente buffers, selectors e channels. O
objetivo introduzir alguns conceitos da figura do prximo slide.
java.nio - Buffers, Channels e Selectors
java.nio - Buffers
Conceitos bsicos
As classes de buffer so a base da API java.nio. Alis, os
buffers so o prprio pacote java.nio porque as outras
classes ficam em pacotes especializados debaixo de
java.nio. A maioria das operaes destas outras classes
usam buffers. Um buffer acumula dados entre operaes
de IO com fins de otimizao de performance. igual ao
armrio de comida onde se guardam as compras da feira
antes de cozinhar.
H uma classe Buffer para cada tipo primitivo no
booleano. Todas as classes so abstratas. Os buffers so
alocados atravs de mtodos estticos.
A classe Buffer define operaes comuns a todos os
buffers.
java.nio - Buffers
java.nio - Buffers
Atributos
Capacity mximo nmero de elementos definido na
criaao.
Limit primeiro elemento que NO pode ser lido ou
gravado.
Position prximo elemento a ser lido ou gravado.
Mark guarda uma posiao na memria para voltar a ela
mais tarde com reset()
Associando um array ao buffer, o chamado wrapping:
char[] charArray = new char[22];
CharBuffer bufferChar = CharBuffer.wrap(charArray);
Duplicando um buffer:
ByteBuffer bufferDup = buffer.duplicate();
Duplicando s uma fatia do buffer:
buffer.position(4).limit(8);
ByteBuffer bufferSlice = buffer.slice();
Criando viso de um ByteBuffer como outro qualquer:
LongBuffer bufferlong = buffer.asLongBuffer();
java.nio - Buffers
Assinaturas dos mtodos da classe Buffer
package java.nio;
public abstract class Buffer {
Ambos so do mesmo tipo;
Ambos tem o mesmo nmero de elementos restantes. A
capacidade no precisa ser a mesma e nem mesmo os
ndices, mas o nmero de elementos desde position at
limit precisa ser igual
Os elementos que podem ser obtidos com get() devem
ser idnticos
Obs.:
a) As transferncias em bloco so sempre com tamanho
fixo.
b) Os 2 ltimos mtodos com parmetros String s
existem em CharBuffer.
java.nio - Byte Buffers e byte order
Byte a unidade fundamental de dados do SO e das
operaes de IO. Todo IO de mais baixo nvel como channels
por exemplo usa objetos da classe ByteBuffer. Esta a
classe com mais mtodos do pacote java.nio.
Ou assim:
little-endian byte order (Intel)
A criao de um ByteBuffer direto feita usando
ByteBuffer.allocateDirect (int capacity)
Os buffers diretos so timos para IO mais so muito mais
custosos para criar do que um buffer comum. A memria
alocada pela chamada de mtodos nativos fora da heap da
JVM e fora do alcance do GC.
Exemplo: alocar memria de vdeo como ByteBuffer direto.
java.nio.channels
Channels
Abstrao que representa uma conexo direta com os
servios de IO do SO.
Canal de transporte eficiente de dados entre ByteBuffers
e as entidades do outro extremo que normalmente so
arquivos ou sockets.
So como um gateway pelo qual podem ser acessados
os servios nativos de IO do SO com o menor overhead.
A API baseada em interfaces. As implementaes
podem depender do SO. A API somente descreve o que
pode ser feito.
Os channels s operam em ByteBuffers. possvel
extender para outros tipos de dados mas IO de baixo
nvel sempre em termos de bytes.
java.nio.channels
Interfaces principais
java.nio.channels
Os channels podem ser unidirecionais ou bidirecionais,
isto , implementam ReadableByteChannel,
WritableByteChannel ou ByteChannel que extende
ambas e assim bidirecional.
Os channels tem uma relao um-para-um com os file
descriptors ou file handlers do SO. So restritos s
caractersticas do servio ao qual esto conectados.
Um channel que implementa WritableByteChannel no
pode gravar em um arquivo marcado como Read Only
pelo SO.
A interface InterruptibleChannel, quando
implementada, apenas indica que o channel pode ser
interrompido.
A API inclui as 2 classes AbstractInterruptibleChannel e
AbstractSelectableChannel em java.nio.channels.spi
com mtodos necessrios para as implementaes
concretas de channels.
java.nio.channels
Criao de channels
Socket channels so criados pelo mtodo factory open()
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress(host, port);
DatagramChannel dc = DatagramChannel.open();
Os file channels no podem ser criados diretamente. So
obtidos usando getChannel() de um objeto de um dos tipos
RandomAccessFile, FileInputStream ou FileOutputStream.
Uso de Channels
Os mtodos read de ReadableByteChannel e write de
WritableByteChannel recebem ByteBuffers e retornam o
nmero de bytes transferidos que pode ser menor do que
o tamanho do buffer. A posio do buffer atualizada.
Channels seqnciais (tipo Stream) podem operar
bloqueados ou no. Uma operao de IO no
bloqueante quando permite a um processo verificar se h
dados na entidade de IO sem estacionar esperando pela
chegada de algum dado. uma caracterstica nativa da
maioria dos SOs.
Um channel no modo no bloqueante nunca adormece a
thread que o chama, sempre retorna imediadamente com
a operao completa ou com o que deu para ser feito
naquele instante.
java.nio.channels
Exemplo de uso tradicional de socket com java.net
java.nio.channels
Os objetos do tipo channel no podem ser reutilizados.
Representam uma conexo especfica com um
determinado servio de IO e encapsulam o estado da
conexo.
Quando um channel fechado a conexo perdida.
Nos channels que implementam InterruptibleChannel, se
uma thread bloqueada em um channel interrompida
(por outra thread), o channel fechado e a thread lana
ClosedByInterruptionException. E mais, se o status de
interrupo da thread est setado (por uma chamada de
interrupt()) e a thread tenta acessar o channel, ento este
imediatamente fechado e a mesma exceo lanada.
java.nio.channels
Scatter / Gather
Um pouco de ingls:
Scatter = disseminate, spread, disperse, sprinkle, etc.
Gather = bring together, assemble, collect,
accumulate, etc.
Scattering:
ReadableByteChannel ByteBuffer[ ]
Gathering:
ByteBuffer[ ] WritableByteChannel
File Channels
Sempre so bloqueantes e no podem ser criados
diretamente.
Usam servios nativos de IO sempre que possvel.
So thread-safe mas nem todas as operaes so multi-
threaded.
garantido que dentro de uma mesma JVM todas as
instncias tero acesso consistente a um arquivo. O
acesso concorrente a arquivos entre diferentes JVMs ou
com aplicaes em outras linguagens depende do SO.
java.nio.channels
File locks do tipo advisory fornecem informaes sobre
os locks usados aos processos que solicitam tal
informao. O SO no garante o lock. O processo
precisa cooperar e respeitar a informao sobre o lock.
File locks do tipo mandatory so mantidos pelo SO e o
file system evitar o acesso de processos s reas
protegidas dos arquivos quer os processos estejam
conscientes do lock ou no.
java.nio.channels
User Kernel
Podemos transferir dados de um channel para outro
diretamente sem usar buffers intermedirios. muito
mais eficiente do que usar read() e write().
Exemplo onde destino um WritableByteChannel:
O mtodo transferTo() escreve no destino mas existe
tambm o mtodo transferFrom() que l de um
ReadableByteChannel para um FileChannel.
java.nio.channels
Socket Channels
SocketChannel, ServerSocketChannel e
DatagramChannel
Podem operar em modo no bloqueante e podem ser
usados com selectors.
Descendem de SelectableChannel e tambm de
InterruptibleChannel.
Usando selectors no necessrio dedicar uma thread
para cada conexo via socket e degradar a performance
com as trocas de contexto entre as muitas threads.
Os sockets channels criam um objeto socket quando
instanciados. Eles delegam as operaes de protocolo a
este objeto a menos que existam mtodos de mesmo
nome nas classes channel.
java.nio.channels
Selectors
Fornecem a possibilidade de selecionar um channel e
verificar se ele est pronto para ser usado sem fazer uma
operao de leitura. Isto permite o chamado IO
multiplexado.
Modo de usar:
1. Criar vrios SelectableChannels e configurar no modo
no bloqueante;
SelectableChannel
Classe abstrata que fornece os mtodos necessrios
para implementar a facilidade de seleo. FileChannels
no extendem esta classe. Os objetos tipo
SelectableChannel podem ser registrados com objetos
Selector junto com uma indicao da operao em que o
Selector est interessado. Um channel pode ser
registrado com vrios Selectors diferentes mas uma vez
s por Selector.
java.nio.channels
Selectors - Observaes
Cada objeto Selector guarda 3 conjuntos de chaves
- Registered key set chaves registradas com o selector;
- Selected key set subconjunto com as chaves
associadas a um channel com ao menos uma operao
pronta de IO de interesse da chave;
- Cancelled key set conjunto com chaves canceladas;
So 4 as operaes que podem ser registradas:
read, write, connect e accept.
Cada operao faz sentido para determinado tipo de
channel. Exemplo: registrar um SocketChannel para
accept resulta em IllegalArgumentException.
Fechamento de um channel
Quando um channel fechado todas as SelectionKeys
associadas so automaticamente invalidadas. Quando
um selector fechado, todos os channels registrados
perdem o registro e suas chaves so invalidadas.
java.nio - Comparao entre java.io e java.nio
A - Simples cpia
in = new FileInputStream(from);
out = new FileOutputStream(to);
while (true) {
int data = in.read();
if (data == -1) {
break;
}
out.write(data);
}
Arquivo Mb Tempo em ms
2541 9003
6616 23504
java.nio - Comparao entre java.io e java.nio
Arquivo Mb Tempo em ms
2541 33
6616 135
17651 203
93548 1867
java.nio - Comparao entre java.io e java.nio
Arquivo Tempo em ms
Mb A B C D
2.541 9003 163 60 33
6.616 23504 405 152 135
17.651 ---- 1270 725 203
93.548 ---- ---- 20275 1867
Muito obrigado !
Luiz A. G. Bastos (Luca) lucabastos@gmail.com