terça-feira, 16 de fevereiro de 2010

Tutorial simples de JNI no Linux c/ GCC

Introdução

O JNI (Java Native Interface) é uma interface que viabiliza interagir a JVM com bibliotecas nativas do SO subjacente. É utilizada principalmente para tarefas de mais baixo nível que a API Java não oferece ou, ainda, quando necessita-se de uma performance maior sem o "overhead" da JVM no caminho.

É importante ressaltar que a utilização de métodos nativos torna sua aplicação dependente de plataforma. Em Linux trabalharemos com arquivos de extensão SO (Shared Objects), já em Windows trabalha-se com DLLs (Dynamic Linked Libraries). O JNI, no entanto, não se limita a somente Linux e Windows, é possível utilizá-lo em outras plataformas (Solaris, AIX, etc) de acordo com a implementação JVM.

Esse tutorial tem o objetivo de mostrar um simples exemplo de utilização do JNI. Diga-se de passagem, a documentação da Sun sobre o assunto é muito rica e os links se encontram nas referências.

Primeiro passo: criar a classe que conterá o(s) método(s) nativo(s).

Crie um diretório "Carnival" (apenas por questão de organização), uma classe e um método com o modificador "native" sem implementação para trabalharmos no exemplo.

public class Carnival
{

// Carregamento da biblioteca que será criada.
static {
System.loadLibrary("Carnival");
}

// Método marcado com modificador "native".
public native void dance(String verse);

public static void main(String[] args) {
new Carnival().dance("...pode chorar, mas chora...");
}
}



Para que a JVM possa "linkar" a chamada do método da classe Carnival com uma biblioteca compartilhada nativa, ela precisará saber o nome. Aqui carregamos a biblioteca assim que a classe Carnival é carregada pela JVM:

static {
System.loadLibrary("Carnival");
}


Logo em seguida declaramos o método "dance()" que será chamado pelo método "main()". Como a implementação de um método "native" será escrita em outra linguagem (C ou C++), não iremos fornecer implementação e terminaremos a declaração com ponto-e-vírgula.

Segundo passo: compilar a classe.

javac Carnival.java


Ela será compilada normalmente, mesmo que as bibliotecas nativas ainda não estejam acessíveis. Você só não conseguirá executar ainda.

Terceiro passo: utilizar o "javah" para gerar os headers em C/C++.

javah -jni Carnival


* Certifique-se que a classe esteja em seu "classpath".

Isso gerará um arquivo Carnival.h que será usado ao criar a implementação do método.

Se quiser, examine o Carnival.h. Você encontrará os protótipos das funções que implementará em seguida.

Quarto passo: implementar o método nativo.

Crie um arquivo chamado Carnival.c e dentro dele virá a implementação do método "dance()".

#include <jni.h>
#include "Carnival.h"
#include <stdio.h>

JNIEXPORT void JNICALL
Java_Carnival_dance(JNIEnv * env, jobject obj, jstring verse)
{
const char * vstr = (*env)->GetStringUTFChars(env, verse, NULL);
printf("%s\n", vstr);
return;
}



Quinto passo: compilar a implementação.

Neste tutorial utilizaremos o GCC. No meu desktop utilizei um Makefile para poupar o trabalho, mas aqui vai o comando direto para compilar.

Antes criaremos um diretório "lib" que irá conter o arquivo "Shared Object" gerado pelo GCC:

mkdir lib

E então compilaremos:

gcc -o lib/libCarnival.so -shared -Wl,-soname,libCarnival.so \
-I/opt/jdk/include \
-I/opt/jdk/include/linux Carnival.c \
-static -lc

É importante lembrar que a biblioteca precisa estar no PATH de bibliotecas do Linux, então defina a variável de ambiente LD_LIBRARY_PATH para o diretório "lib" criado:

LD_LIBRARY_PATH="$(pwd)/lib"
export LD_LIBRARY_PATH

Com isso, ao executar a classe, a "JVM" conseguirá encontrar a biblioteca libCarnival.so.

Sexto (e último) passo: executar.

java Carnival

Espera-se, aqui, que seja impressa a mensagem que foi enviada através do parâmetro "verse" (String) pelo método "dance()" da classe Java Carnival.

Referências:

http://java.sun.com/docs/books/jni/html/start.html#26346

http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html

http://www.ibm.com/developerworks/aix/library/au-JNI_AIX_PAPER.html

Quando as chamadas polimórficas mudam tudo...

Estudando p/ o exame SCJP, ao fazer uma revisão de assuntos dos primeiros capítulos antes de prosseguir, notei uma coisa que não foi abordada pelo livro.

Aparentemente, fazer a chamada polimórfica de um método declarado na interface geraria o mesmo resultado:
interface Doable {
public void doSomething();
}

class Okay implements Doable {
@Override

public void doSomething() {
System.out.println("Oi, sou o método doSomething subscrito em Okay.");
}

public static void main(String[] args) {
Okay o = new Okay();
Doable d = o;

// Aparentemente o comportamento é o mesmo.
d.doSomething(); // OK
o.doSomething(); // OK
}
}
Será, então, impresso:
Oi, sou o método doSomething subscrito em Okay.
Oi, sou o método doSomething subscrito em Okay.
Ora, basta declarar o lançamento de exceções na declaração do método "doSomething()" da interface que tudo muda. Veja:
class BoringHolidayException extends Exception {}

interface Doable {

public void doSomething() throws BoringHolidayException;
}

class Okay implements Doable {
// Não declara a exceção BoringHolidayException.
@Override
public void doSomething() {
System.out.println("Oi, sou o método doSomething subscrito em Okay.");
}

public static void main(String[] args) {
Okay o = new Okay();
Doable d = o;

// Como a declarção de doSomething() na interface
// declara lançar a
exceção BoringHolidayException,
// a chamada polimórfica do método
através de uma
// referência à interface exigirá tratamento das exceções.

d.doSomething(); // Erro em tempo de compilação.

// Enquanto chamar o método diretamente por uma
// referência Okay não irá lançar a exceção, uma
// vez que, propositalmente, o método subscritor
// não lança nenhuma exceção.
o.doSomething(); // OK. Sem problemas.
}
}

O que já se sabe (se você também já leu o capítulo 1 do mencionado livro) é que duas das regras de subscrição são:
  1. não declarar exceções mais abrangentes e;
  2. não declarar novas exceções no método subscritor.
Embora você nem precise declarar qualquer exceção declarada pelo método subscrito, nunca faça nenhuma dessas duas coisas.

Então, neste caso, é necessário tratar a exceção declarada pela chamada polimórfica de doSomething(), mas não é necessário se preocupar pela chamada a partir da referência Okay.

Certo! Fiz esse post, porque sei que a SCJP adora pegadinhas desse tipo, então, tendo escrito aqui, não vou esquecer na hora da prova :ô) e, quem sabe, algum dia, alguém se preocupe em pesquisar isso no Google...

sexta-feira, 20 de novembro de 2009

Resumo do cap. 1 do PMBOK

Resumo PMBOK

Autor: Hiram Castelo Branco T. Nascimento

Capítulo 1 – A estrutura do gerenciamento de projetos

Introdução

“ O Conjunto de conhecimentos em gerenciamento de projetos é a soma dos conhecimentos intrínsecos à profissão de gerenciamento de projetos.” (PMBOK, 2004)

Objetivos do PMBOK

“ O principal objetivo do Guia PMBOK® é identificar o subconjunto do Conjunto de conhecimentos em gerenciamento de projetos que é amplamente reconhecido como boa prática.” (PMBOK, 2004)

“ 'Boa prática' significa que existe acordo geral de que a aplicação correta dessas habilidades, ferramentas e técnicas podem aumentar as chances de sucesso em uma ampla série de projetos diferentes.” (PMBOK, 2004)

O que é um projeto?

Um projeto é um esforço temporário empreendido para criar um produto, serviço ou resultado exclusivo.

Empreender: Experimentar, procurar fazer, tomar iniciativa de ação, tarefa, realização etc.

Temporário:significa que todos os projetos possuem um início e um final definidos.Projetosnãosão esforços contínuos.

Produtos, serviços ou resultados exclusivos:cada um desses é uma instância singular.

Elaboração progressiva: significa desenvolver em etapas e continuar por incrementos. Não deve ser confundida com aumento do escopo.

Observação sobre iterações:“É importante observar que muitos processos dentro do gerenciamento de projetos são iterativos devido à existência, e necessidade, de uma elaboração progressiva em um projeto durante todo o ciclo de vida do projeto.”

É importante, também, não confundir a necessidade de iterações por erros na definição de escopo (o que é ruim), mas sim pela elaboração progressiva (o que é bom e necessário).

Sabe-se, portanto, que a medida que uma equipe de projetos ganha experiência em um tipo de projeto, todo conhecimento adquirido é útil para uma melhor gerência nos próximos empreendimentos. É importante haver um acervo para armazenar tais conhecimentos adquiridos.

Projetos x Operações

“ Os projetos e as operações diferem principalmente no fato de que as operações são contínuas e repetitivas, enquanto os projetos são temporários e exclusivos.” (PMBOK, 2004)

“ Os projetos são diferentes porque o projeto termina quando seus objetivos específicos foram atingidos, enquanto as operações adotam um novo conjunto de objetivos e o trabalho continua.” (PMBOK, 2004)

Projetos e planejamento estratégico

“ Os projetos são um meio de organizar atividades que não podem ser abordadas dentro dos limites operacionais normais da organização. Os projetos são, portanto, frequentemente utilizados como um meio de atingir o plano estratégico de uma organização, seja a equipe do projeto formada por funcionários da organização ou um prestador de serviços contratado.” (PMBOK, 2004)

Projetos são, em geral, concebidos e autorizados em resposta a uma das seguintes considerações estratégicas:

  • Demanda de mercado

  • Necessidade organizacional

  • Requisito legal

  • Solicitação de um cliente

  • Avanço tecnológico

O que é gerenciamento de projetos?

“ O gerenciamento de projetos é a aplicação de conhecimento, habilidades, ferramentas e técnicas às atividades do projeto a fim de atender aos seus requisitos.”

Segundo o PMBOK, o gerenciamento de projetos é realizado através da aplicação e da integração dos seguintes processos de gerenciamento de projetos:

  • iniciação,

  • planejamento,

  • execução,

  • monitoramento e controle, e

  • encerramento.

“ O gerente de projetos é a pessoa responsável pela realização dos objetivos do projeto.”p (PMBOK, 2004)

“ Gerenciar um projeto inclui:

  • Identificação das necessidades

  • Estabelecimento de objetivos claros e alcançáveis

  • Balanceamento das demandas conflitantes de qualidade, escopo, tempo e custo

  • Adaptação das especificações, dos planos e da abordagem às diferentes preocupações e expectativas das diversas partes interessadas.” (PMBOK, 2004)

Observação sobre qualidade: “Projetos de alta qualidade entregam o produto, serviço ou resultado solicitado dentro do escopo, no prazo e dentro do orçamento.” (PMBOK, 2004)

domingo, 12 de abril de 2009

A famigerada java.lang.NullPointerException

Hoje eu respondi a um post sobre Arrays criado por um usuário de um dos fóruns Java que freqüento.

A dúvida era simples: como verificar se um elemento do array era nulo. O que me intrigou durante uns testes que eu fiz é que a exceção NullPointerException é lançada em muitos contextos diferentes. Decidi, então, pesquisar sobre mais detalhes dessa "famosa" exceção que, apesar de muito popular, gera dúvidas em programadores Java iniciantes - como eu - sobre em que casos ela é de fato lançada.

A NullPointerException é uma subclasse da RuntimeException e é lançada sempre que um valor null é fornecido em situações em que um objeto, ou uma referência a um objeto, precisa ser fornecido.

As situações específicas que causam o lançamento dessa exceção são:

  • A chamada de um método de instância de um objeto nulo. Por exemplo, quando um objeto é apenas inicializado e não instanciado. Assim, ele não pode ter um de seus métodos de instância chamado. Por distração, esse problema ocorre frequentemente quando se trabalha com arrays de objetos.

  • O acesso ou tentativa de modificação de um atributo de um objeto nulo.

Os outros três principais casos merecem exemplos em código:

  • A tentativa de se tomar o tamanho de um objeto nulo, ou seja, com referência a null, como se ele fosse um array.

String str = null;
int l;
l = str.length();
  • As tentativas de acesso ou modificação os elementos de um objeto nulo como se ele fosse um array. Talvez essa seja a causa mais comum. Segue o exemplo:

String str = null;
str[2] = "vai dar problema!";
  • O lançamento de um objeto nulo como se ele fosse uma subclasse de Throwable. Veja:

if(args.length == 0) thrownull;

Para não dizer que não falei de flores, o tipo null, segundo as especificações da JVM abstrata, isto é, sem distinção de implementações da JVM, está intimamente relacionado a referências. Ele é nada mais nada menos que uma referência nula, ou a nada.

A documentação da Java API aconselha que as aplicações deveriam lançar a exceção NullPointerException nos demais casos em que um valor null é fornecido em lugar de um objeto.

Em caso de dúvidas postem comentários.