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.