RPM API Pada Java Dengan JNI
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/





susilo budi utomo berkata,
Maret 29, 2008 pada 8:38 am
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)
fuad berkata,
Maret 29, 2008 pada 9:45 am
Biasanya ini karena class yang dimaksud tidak ada dalam classpath. Solusinya bisa dengan mengkopi library *.so atau *.dll ke folder jre/lib/i386/
turiscai berkata,
Juli 31, 2008 pada 2:04 am
silahkan tambah link pada Blog saya
hilal berkata,
Agustus 19, 2008 pada 2:49 am
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..
hilal-nuha berkata,
Agustus 19, 2008 pada 2:51 am
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
fuad berkata,
Agustus 19, 2008 pada 1:22 pm
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.
triaditya berkata,
September 11, 2008 pada 3:08 am
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
Q.cubee berkata,
Mei 21, 2009 pada 12:44 pm
mas lok jni ma vb gimana?
tolong kasih contoh, soalnya cari kemana-mana dapatnya dapatnya jni dan C..
maklum masih baru di java….
diaz_ramadhian berkata,
Agustus 6, 2009 pada 2:12 am
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