RPM API Pada Java Dengan JNI

Sebelum membahas lebih lanjut, saya akan memberi perkenalan singkat apa itu JNI. JNI adalah kependekan dari Java Native Interface. Dengan JNI, kelas kelas di Java bisa memanggil prosedur/method yang dibuat dengan menggunakan C/C++ dan sebaliknya program yang kita buat dengan C/C++ bisa menggunakan kelas kelas yang dibuat dengan Java.
Pada Tutorial ini saya akan membahas bagaimana membuat program Java yang mencetak ke konsole dependency dari suatu paket RPM yang telah terinstall sebelumnya.

Catatan:

Tutorial ini dibuat dan dicoba pada sistem operasi linux, dengan Java terinstall pada /usr/java/jdk1.5.0_06/ dan direktori kerja pada /home/fuad/java/JNI

Langkah 1:
Ketiklah kode di bawah ini dan simpan pada file dengan nama RpmProject.java:

public class RpmProject {
public native static Object[] getDependencies();

static{
System.loadLibrary(“RpmProject”);
}
public static void main(String[] args) {
Object [] str=RpmProject.getDependencies();
for(int i=0; i<str.length; i++)
System.out.println(str[i]);
}

}

metode getDescriptionAndDependencies() adalah metode yang akan diimplementasikan dengan cara native dengan menggunakan C/C++. Untuk memberitahu ini pada kompiler maka kita memberinya keyword native.

static{
System.loadLibrary(“RpmProject”);
}

kode di atas digunakan untuk memuat(menload) library yang bernama(“libRpmProject”, perhatikan library yang dimuat adalah libRpmProject.so/.dll bukan RpmProject.so/.dll) Library yang dimuat adalah library yang berisi implementasi dari method native, dalam tutorial ini adalah method getDescriptionAndDependencies().

Langkah 2:
Kompile kelas di atas
[fuad@fuad JNI]$ javac RpmProject.java

Selanjutnya buat file header kelas di atas dengan
[fuad@fuad JNI]$ gjnih RpmProject, jika menggunakan java GNU atau
[fuad@fuad JNI]$ javah RpmProject, jika menggunakan Java Sun.
Hal yang perlu diperhatikan di sini adalah yang menjadi parameter adalah class pada java(tidak berekstensi) bukan kode sumber(*.java).
langkah di atas akan menghasilkan header “RpmProject.h”.

Langkah 3:
Buka file “RpmProject.h” tambahkan variabel pada kedua parameter, dengan nama terserah anda.
file awal “RpmProject.h” :
/* DO NOT EDIT THIS FILE – it is machine generated */
#include <jni.h>
/* Header for class RpmProject */

#ifndef _Included_RpmProject
#define _Included_RpmProject
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: RpmProject
* Method: getDescriptionAndDependencies
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

file “RpmProject.h” setelah diedit:

/* DO NOT EDIT THIS FILE – it is machine generated */
#include <jni.h>
/* Header for class RpmProject */

#ifndef _Included_RpmProject
#define _Included_RpmProject
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: RpmProject
* Method: getDescriptionAndDependencies
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies
(JNIEnv *env, jclass cl);

#ifdef __cplusplus
}
#endif
#endif
Langkah 4:
Buat implementasi dari file header di atas dengan nama RpmProject.c#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmds.h>

#include “RpmProject.h”
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies (JNIEnv *env, jclass cl){
rpmdb * pdb;
rpmReadConfigFiles(NULL,NULL);
printf(“Config files read \n”);

int dbStatus = rpmdbOpen(“”, &pdb, O_RDONLY, 0644);

if (dbStatus) {
// error opening
printf(“Error on opening RPM Database: (%d) %s\n”, rpmErrorCode(), rpmErrorString());
} else {
printf(“RPM Database opened!\n”);
}

rpmdbMatchIterator mi = rpmdbInitIterator(pdb, RPMDBI_PACKAGES, NULL, 0);
rpmdbSetIteratorRE(mi,RPMTAG_NAME, RPMMIRE_DEFAULT, “gstreamer”);
printf(“Iterator initialized!\n”);
Header header;
int i;
jobjectArray array;
while (header = rpmdbNextIterator(mi)) {
rpmds Rpmds=rpmdsNew(header, RPMTAG_REQUIRENAME , (RPMSENSE_EQUAL|RPMSENSE_LESS));
jstring kal=(*env)->FindClass(env,”java/lang/String”);
array = (*env)->NewObjectArray(env,rpmdsCount(Rpmds),kal,NULL);
for(i=0; i<rpmdsCount(Rpmds); i++){
rpmdsNext(Rpmds);
(*env)->SetObjectArrayElement(env, array, i, (*env)->NewStringUTF(env,rpmdsN(Rpmds)));
}
rpmdsFree(Rpmds);

}

rpmdbFreeIterator(mi);
printf(“Iterator Finished!\n”);
rpmdbClose(pdb);
printf(“RPM Database closed!\n”);

return array;

}

Penjelasan

rpmReadConfigFiles(NULL,NULL);, berfungsi membaca konfigurasi dari database rpm yang ada pada sebuah sistem/komputer. kode ini wajib adanya.

int dbStatus = rpmdbOpen(“”, &pdb, O_RDONLY, 0644); berfungsi membuka database RPM

rpmdbMatchIterator mi = rpmdbInitIterator(pdb, RPMDBI_PACKAGES, NULL, 0); berfungsi mengambil semua paket/software yang ada pada database.

rpmdbSetIteratorRE(mi,RPMTAG_NAME, RPMMIRE_DEFAULT, “gstreamer”); berfungsi memfilter/menyaring paket yang telah dimuat tadi berdasarkan nama paket(RPMTAG_NAME). Nama paket yang digunakan di sini adalah “gstreamer”.

jobjectArray array; adalah variabel khsusus pada JNI. untuk komunikasi antara Java dengan C/C++ digunakan suatu variabel khusus (http://java.sun.com/developer/onlineTraining/Programming/JDCBook/index.html). Karena pada metode getDependencies pada kelas Java tadi meminta mengembalikan nilai yag bertipe array objek, maka nilai yang dikembalikan pada fungsi ini harus variabel JNI yang bertipe jobjectArray.

rpmds Rpmds=rpmdsNew(header, RPMTAG_REQUIRENAME , (RPMSENSE_EQUAL|RPMSENSE_LESS));
Kode di atas mengambil semua dependency dari sebuah paker berdasarkan nilai headernya

jstring kal=(*env)->FindClass(env,”java/lang/String”);
Memanggil kelas pada java yang akan digunakan pada pengembalian nilai nanti.

array = (*env)->NewObjectArray(env,rpmdsCount(Rpmds),kal,NULL);
Membuat array objek baru yang berisi string(sesuai tipe variabel “kal”) dengan panjang sebanyak rpmdsCount(Rpmds)

for(i=0; i<rpmdsCount(Rpmds); i++){
rpmdsNext(Rpmds);
(*env)->SetObjectArrayElement(env, array, i, (*env)->NewStringUTF(env,rpmdsN(Rpmds)));
}

Untuk setiap dependency yang dimuat akan dimasukkan ke dalam variabel array pada indeks i.

Langkah 5:

Kompile file di atas
[fuad@fuad JNI]$ gcc -c -fPIC -I/usr/java/jdk1.5.0_06/include/ -I/usr/java/jdk1.5.0_06/include/linux/ RpmProject.c
hasil dari kompilasi di atas adalah file RpmProject.o

Selanjutnya buat library libRpmProject.so dengan cara
[fuad@fuad JNI]$ gcc -shared -o libRpmProject.so RpmProject.o -lrpm -lrpmdb
hasil dari kompilasi di atas adalah file libRpmProject.so

Langkah 6:

Setelah kelima langkah di atas berhasil maka kelas java “RpmProject” sudah bisa dijalankan
[fuad@fuad JNI]$ java RpmProject

jika saat menjalankan anda mendapatkan error:
Exception in thread “main” java.lang.UnsatisfiedLinkError: no RpmProject in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:992)
at RpmProject.<clinit>(RpmProject.java:10)
maka anda harus terlebih dahulu mengeset variabel LD_LIBRARY_PATH yang menunjuk file libRpmProject.so.
[fuad@fuad JNI]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/fuad/java/JNI/

9 Komentar »

  1. susilo budi utomo said,

    Bagaimana cara mengatasinya,saya pakai netbeans 5.5,terima kasih,tolong jawab di email saya saja
    Exception in thread “main” java.lang.UnsatisfiedLinkError: no testjoystick in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
    at java.lang.Runtime.loadLibrary0(Runtime.java:822)
    at java.lang.System.loadLibrary(System.java:992)
    at testjoystick.Joystick.(Joystick.java:24)
    at testjoystick.Sample.main(Sample.java:19)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)

  2. fuad said,

    Biasanya ini karena class yang dimaksud tidak ada dalam classpath. Solusinya bisa dengan mengkopi library *.so atau *.dll ke folder jre/lib/i386/

  3. turiscai said,

    silahkan tambah link pada Blog saya

  4. hilal said,

    asssalamualaikum..
    mohon bimbingannya..
    saya sedang mengerjakan tugas akhir dan menggunakan J2ME sebagai proyeknya.
    kunci dari tugas ini adalah bagai mana saya bisa membaca isi memori dari suatu alamat pada ponsel..namun pada j2me tidak ada fitur tersebut.. berdasarkan saran dari teman2 dengan JNI saya bisa mendapat celah untuk itu..mohon bimbingannya..

  5. hilal-nuha said,

    asssalamualaikum..
    mohon bimbingannya..
    saya sedang mengerjakan tugas akhir dan menggunakan J2ME sebagai proyeknya.
    kunci dari tugas ini adalah bagai mana saya bisa membaca isi memori dari suatu alamat pada ponsel..namun pada j2me tidak ada fitur tersebut.. berdasarkan saran dari teman2 dengan JNI saya bisa mendapat celah untuk itu..mohon bimbingannya..ya

  6. fuad said,

    maaf, namun setau saya j2me tidak bisa menggunakan JNI,

    JNI merupakan interface/ cara untuk membuat metod di Java tapi implementasi/kode dari metod ini dari bahasa C/C++, sedang kebanyakan handphone yang menggunakan J2me tidak mengijinkan hal ini. mungkin bisa coba pake symbian atau android.

  7. triaditya said,

    pada J2ME dng konfigurasi CDC mempunyai fitur JNI. JNI ini merupakan fitur dari CVM (JVM yang digunakan pada J2ME konfigurasi CDC). mungkin anda dapat membaca buku dengan judul ‘membuat sendiri aplikasi ponsel’ penulis : Dr.Suyoto

  8. Q.cubee said,

    mas lok jni ma vb gimana?
    tolong kasih contoh, soalnya cari kemana-mana dapatnya dapatnya jni dan C..
    maklum masih baru di java….

  9. mas.. minta tolong donk, saya punya banyak obyek yang ingin saya kasi fungsi get URL.. ( bantuin cara meringkasnya dunk … )
    seperti ini :

    prov1.onRelease = function(){ getURL (“?page=report&idprov=1”); }
    prov2.onRelease = function(){ getURL (“?page=report&idprov=2”); }
    prov3.onRelease = function(){ getURL (“?page=report&idprov=3”); }
    prov4.onRelease = function(){ getURL (“?page=report&idprov=4”); }
    prov5.onRelease = function(){ getURL (“?page=report&idprov=5”); }
    prov6.onRelease = function(){ getURL (“?page=report&idprov=6”); }
    prov7.onRelease = function(){ getURL (“?page=report&idprov=7”); }

    soalnya obyek nya ada 100 .dari prov1 sampai prov100.. gimana ya ?
    terimakasie


Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: