'Open Source/Java'에 해당되는 글 6건

  1. 2012.12.05 RMI 제작 및 사용법
  2. 2012.10.30 C Code JNI 사용 (Class, 인수 사용등) 1
  3. 2012.10.30 Jni C 사용 방법

RMI 제작 및 사용법

|

Remote로 사용할 Data Object

import java.io.*;

public class TestDataObj implements Serializable
{
    private int Tag;
    private int Stat;

    public void setTag(int iTag) { this.TagNo = iTag; }
    public void setStat(int iStat)   { this.Stat = iStat; }

    public int getTag()   { return this.Tag; }
    public int getStat()    { return this.Stat; }
}

넘길 Object를 직렬화 해줘야 하기 때문에 implements Serializable 해줘야 한다.

Interface 선언

import java.rmi.*;

public interface IReadData extends Remote
{
    public TestDataObj GetTestDataObj() throws RemoteException;
}

rmi에서 사용할  Data Object

import java.rmi.server.*;
import java.rmi.*;
import java.io.*;

public class ReadDataImpl extends UnicastRemoteObject implements IReadData
{
    public ReadDataImpl() throws RemoteException
    {
        super();
    }
    public TestDataObj GetTestDataObj()
    {
        TestDataObj Data = new TestDataObj();
        Data.setTag(1);
        Data.setStat(5);
        return rtlData;
    }
}

rmi Server

import java.rmi.*;
import java.net.*;

public class RmiShmServer
{
    public static void main(String[] args)
    {
        try
        {
            ReadDataImpl remoteObj = new ReadDataImpl ();
            Naming.rebind("rmi://localhost:1099/TestRemote", remoteObj);
            System.out.println("Test Remote Obj Bound to the registry");
        }
        catch (RemoteException e)
        {
            System.err.println("incoming method call" + e);
        }
        catch (MalformedURLException e)
        {
            System.err.println("Checking URL " + e);
        }
    }
}

rmi 주소를 넣어 줄시 rmi://localhost:[port]/[Remote Object] 형식으로 만들어 준다

나중에 rmiregistry 등록시 port를 기입 해준다.

rmi Client

import java.rmi.*;
import java.net.*;

public class RmiShmClinet
{
    public static void main(String[] args)
    {
        try
        {
            Object obj = Naming.lookup("rmi://localhost:1099/TestRemote");
            IReadData remoteObj = (IReadData)obj;
            TestDataObj Data = remoteObj.GetTestDataObj();
            System.out.println(Data.getTag() + ":" + Data.getStat());
        }
        catch (RemoteException e)
        {
            System.out.println("Somthig has gone wrong during reote method call.." + e);
        }
        catch (NotBoundException e)
        {
            System.out.println("Could't Bound.. ");
        }
        catch (java.net.MalformedURLException e)
        {
            System.out.println("Check url String..");
        }
    }
}

Server에서 선언한 주소를 사용하여 Remote Object를 바라본다.


unix 명령어

1차 console

prompt>javac *.java

prompt>rmic ReadDataImpl

prompt>rmiregistry 1099 &

(Background로 rmiregistry 실행)

prompt>java RmiShmServer


2차 console

prompt>java RmiShmClinet

Data 확인


Compile이 잘 되지 않을 경우 profile의 classpath를 잡아 준다.

CLASSPATH=경로:.

export CLASSPATH

대략 이런식이 되겠지?!




And

C Code JNI 사용 (Class, 인수 사용등)

|

ShmData.java

 package SharedMemory;

public class ShmData{
    public int TagData;
    public int AnalogData;
    public String Comment;


    public void setTagData(int iTagData) { this.TagData = iTagData; }

    public void setAnalogData(int iAnalogData) { this.AnalogData = iAnalogData; }

    public void setComment(String strComment) { this.Comment = strComment; }

    public int getTagData() { return this.TagData; }

    public int getAnalogData() { return this.AnalogData; }

    public String getComment() { return this.Comment; }

}


이 같은 Java Class의 형식을 JNI를 이용하여 Return 하고자 할 경우 C Code File의 작성


JNIEXPORT jobject JNICALL Java_SharedMemory_MemoryRead_Data1

(JNIEnv *env, jobject obj, jint iIndex)

{

    int iTagData = 100;

    int iAnalogData = 1200;

    char strComment[100];

    memset(strComment, 0x00, sizeof(strComment));

    sprintf(strComment, "%s", "Jni Test !!");


    jclass targetClass;

    jmethodID mid;

    jobject newObject;

    jfieldID fid;

    jint result;

    jstring Comment;


    targetClass = (*env)->FindClass(env, "SharedMemory/ShmData");


    // 생성자 찾기

    mid = (*env)->GetMethodID(env, targetClass, "<init>", "()V");


    // 객체 생성(객체 레퍼런스 반환)

    newObject = (*env)->NewObject(env, targetClass, mid, "()V");


    // JniObject 객체의 intField 필드값 설정

    fid = (*env)->GetFieldID(env, targetClass, "TagData", "I");

    (*env)->SetIntField(env, newObject, fid, iTagData);


    fid = (*env)->GetFieldID(env, targetClass, "AnalogData", "I");

    (*env)->SetIntField(env, newObject, fid, iAnalogData );


    fid = (*env)->GetFieldID(env, targetClass, "Comment", "Ljava/lang/String;");

    Comment = (*env)->NewStringUTF(env, strComment);

    (*env)->SetObjectField(env, newObject, fid, Comment);


    return newObject;

위 Code는 JNI를 기반으로 한 C Code이다.

return형을 보자면 jobject 형이므로 Code안에서 return할 jobject newObject를 선언하였다.

그리고 java Code로는 class가 기준이 되므로 C와 java class를 연결할 jclass targetClass를 선언 하였다.


targetClass = (*env)->FindClass(env, "SharedMemory/ShmData");

SharedMemory/ShmData Class를 targetClass에 설정한다.


newObject = (*env)->NewObject(env, targetClass, mid, "()V");

newObject로 targetClass의 Instance를 생성하고 생성자를 실행한다.


fid = (*env)->GetFieldID(env, targetClass, "TagData", "I");

fid에 field(Class 변수)를 설정한다. 변수명은 TagData이고 Type는 I 즉 int Type이다.


(*env)->SetIntField(env, newObject, fid, iTagData);

설정된 Field에 값을 설정한다.


fid = (*env)->GetFieldID(env, targetClass, "Comment", "Ljava/lang/String;");

fid에 field(Class 변수)를 설정한다. 변수명은 Comment이고 Type는 Ljava/lang/String 즉 String Type이다.

Comment = (*env)->NewStringUTF(env, strComment);

jstring형으로 Data를 만들어 준다. c char 배열 또는 포인터 형과 java의 string의 관리 형태가 많이 다르기 때문에 이러한 형태를 취하는게 아닐까 싶다.


Instance에 값을 전부 설정했다면 return newObject를 하여 java에서 받을 수 있게 해준다.


위에서 주의 해야 할 것은 GetFieldID에서는 targetClass를 사용 하였지만 SetIntField 또는 SetObjectField시에는 NewObject 를 사용했다는 점이다.

And

Jni C 사용 방법

|

javah를 사용하여 C Header File을 생성 하였다면 그 형식은  Package_Class.h 형식이 될 것이다.

File을 open 하면 Source.Java File의 native 뒷부분 정의 된 함수가 Header 로 정의되가 된다.

형식은 

JNIEXPORT jobject JNICALL Java_Package_Class_NativeFunction(JNIEnv *, Java Parameter);


EX) Package : SharedMemory

      Class : MemoryRead

      NativeFunction : Data1(int Index)

JNIEXPORT jobject JNICALL Java_SharedMemory_MemoryRead_Data1(JNIEnv *, jobject, jint);


C Header File에서 정의된 함수를 기준으로 Soucre Code를 작성하여 라이브러리 형식으로 만든뒤 Java에서 Call 하여 사용하는 방식을 취하면 된다.


Source를 제작 하여 컴파일 후 라이브러리로 만든 파일의 위치는 Java Class Package의 상위에 위치시키면 된다.


EX ) Package Class File 위치 = :/JniTest/Package

       C 라이브러리 위치  = :/JniTest


C Source 제작


Jni로 생성된 Header File을 inlucde 하여 Coding 하면 된다.


위 예제를 기준으로 Code를 작성하면


#include "SharedMemory_MemoryRead.h"

JNIEXPORT jobject JNICALL Java_SharedMemory_MemoryRead_Data1
  (JNIEnv *env, jobject obj, jint Index)

{

}


Function 내용은 원하는 걸로 채우면 된다!!

jint Index 의 경우 그냥 int Type과 동일하게 하여 작성해 나가면 된다.


java에서의 사용법


MemoryRead.java


package SharedMemory;


import java.util.ArrayList;


public class MemoryRead{

    native ShmData Data1(int Index);


    static{

        try{

            System.loadLibrary("ShmRead");

        }catch(Exception e)

            e.printStackTrace();

        }

    }


    public ArrayList<ShmData> GetShmData()

    {

        ArrayList<ShmData> Data = new ArrayList<ShmData>();


        for(int i = 0 ; i < MAX_DATA; i++)

        {

            ShmData Tmp = Data1(i);

            Data.add(Tmp);

        }

        return Data;

    }

}


Java Sample Code를 작성하자면 대략 위와 같은 형태가 될 것이다.

여기서 System.loadLibrary("ShmRead"); 라인의 ShmRead는 C로 제작된 라이브러리

libShmRead.so file을 참조 한다는 이야기가 되겠다.




And
prev | 1 | 2 | next