'java core'에 해당되는 글 237건

  1. 2005.05.13 millisecond를 가지고 구하기
  2. 2005.05.12 java 5.0 enum.
  3. 2005.05.11 jdk 5.0 static import test code
  4. 2005.05.11 jdk 5.0 Annotation, Enum Test code
  5. 2005.05.11 jdk 5.0 Annotation Test Code
  6. 2005.05.11 [펌] RMI(Remote Method Invocation)
  7. 2005.04.25 jdk 5.0) In runtime, java compile.
  8. 2005.04.25 jar
  9. 2005.03.26 Runtime in jdk5.0
  10. 2005.03.18 Annotation

long milliseconds;
int seconds = (milliseconds/1000)%60;
int minutes = (milliseconds/60000)%60;

int hours = (milliseconds/3600000)%24;
int days = milliseconds/(24*60*60*1000);

의외로 많이 써서..

산수는 의외로 귀찮다구..

'java core' 카테고리의 다른 글

[TIP]자바 실행, 컴파일때 shell 이용법  (0) 2005.06.11
Runtime  (0) 2005.06.06
java 5.0 enum.  (0) 2005.05.12
jdk 5.0 static import test code  (0) 2005.05.11
jdk 5.0 Annotation, Enum Test code  (0) 2005.05.11
Posted by '김용환'
,

java 5.0 enum.

java core 2005. 5. 12. 19:04

java 의 enum은 컴파일러가 지원하는 primitive 타입이 아니라 컴파일러가 클래스로 변환시킨다.
Enum 클래스를 상속받은 static final class로서, 내부 요소들은 해당 클래스의 인스턴스를 가진다.

public class EnumType {
    public enum Editor {A1, A2};
    public static void main(String[] args) {
        System.out.println(Editor.A1);
    }
}

jad로 변환시키니, 다음과 같이 나왔다.


// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) fieldsfirst nonlb space
// Source File Name:   EnumType.java

import java.io.PrintStream;

public class EnumType {
    public static final class Editor extends Enum {

        public static final Editor A1;
        public static final Editor A2;
        private static final Editor $VALUES[];

        public static final Editor[] values() {
            return (Editor[])$VALUES.clone();
        }

        public static Editor valueOf(String s) {
            return (Editor)Enum.valueOf(EnumType$Editor, s);
        }

        static  {
            A1 = new Editor("A1", 0);
            A2 = new Editor("A2", 1);
            $VALUES = (new Editor[] {
                A1, A2
            });
        }

        private Editor(String s, int i) {
            super(s, i);
        }
    }


    public EnumType() {
    }

    public static void main(String args[]) {
        System.out.println(Editor.A1);
    }
}

'java core' 카테고리의 다른 글

Runtime  (0) 2005.06.06
millisecond를 가지고 구하기  (0) 2005.05.13
jdk 5.0 static import test code  (0) 2005.05.11
jdk 5.0 Annotation, Enum Test code  (0) 2005.05.11
jdk 5.0 Annotation Test Code  (0) 2005.05.11
Posted by '김용환'
,

import static java.lang.Math.*;
import static a.StaticImportTest.*;
public class StaticImport {
    public static void main(String[] args) {
        System.out.println(print());
    }
}

 

주의할 점은 import static이라는 점과, 항상 클래스뒤에 필드, 메소드를 의미한다는 의미로 해석해야한다는 것이다.

import static java.lang.Math.*;

이 문장은 Math 클래스의 static 필드, 메소드를 바로 호출 할 수 있다는 의미이다.

'java core' 카테고리의 다른 글

millisecond를 가지고 구하기  (0) 2005.05.13
java 5.0 enum.  (0) 2005.05.12
jdk 5.0 Annotation, Enum Test code  (0) 2005.05.11
jdk 5.0 Annotation Test Code  (0) 2005.05.11
[펌] RMI(Remote Method Invocation)  (0) 2005.05.11
Posted by '김용환'
,

자바 5.0의 Enum, Annotation Test Code이다.

실행결과는 따로 적지 않았다. 대충 만든거라, 약간 어설플 수도 있다.

 


import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface debug {
    boolean devbuild() default false;
    int counter();
}

@Retention(RetentionPolicy.RUNTIME)
@interface Java {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@interface  ID {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@interface Desc {
    String value();
}

@ID("1")
public class MetaTest {

    @Java("123712831783")
    public String a;

    /*
    public enum Type {
        E1("aa"), E2("bb");
        private final String value;
        Type(String value) { this.value = value; }
        public String value() { return value; }
    }
    public Type xType = Type.E1;
    */
    public enum DescEnum {  X1,  X2 };
    public DescEnum de = DescEnum.X1;

    public void de(DescEnum m) {
        if (DescEnum.X1.equals(m)) {
            System.out.println("changed X1");
        } else {
            System.out.println("changed X2");
        }
    }
    /*final boolean production = true;
    @debug(devbuild = production, counter=1) public void testMethod() {}

    public MetaTest() {
        System.out.println(this);
    }*/

    public static void main(String[] args) {
        MetaTest mt = new MetaTest();
        ///////////////////////////////////////////////////////////////
        // de 필드에 enum element의 특정값 넣기.?
        ///////////////////////////////////////////////////////////////

        try {
            Field field = mt.getClass().getField("de");
            System.out.println(field.getType());
            Class cls = field.getType();
            if (cls.isEnum()) {
                System.out.println("c");
            }
            Method method = cls.getMethod("valueOf", String.class);
            Object o = method.invoke(cls, new Object[] { "X2" });
            System.out.println("name : f.getName() : " + o);
            field.set(mt, o);
            System.out.println("result : " + mt.de);

            //------------------------------------------------------
            Method method2 = mt.getClass().getMethod("de", cls);
            Class cls2 = method2.getParameterTypes()[0];
            System.out.println("oj : " + cls2);
            if (cls2.isEnum()) {
                System.out.println("xx");
                Method mtd = cls2.getMethod("valueOf", String.class);
                Object o2 = mtd.invoke(cls2, new Object[] { "X1" });
                System.out.println("o : " + o2);
                method2.invoke(mt, o2);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        ///////////////////////////////////////////////////////////////
        // 
        ///////////////////////////////////////////////////////////////

        /*
        ///////////////////////////////////////////////////////////////
        //  de 필드를 통해서 해당 값이 어떤것인지 알아오기.
        ///////////////////////////////////////////////////////////////

        try {
            Field field = mt.getClass().getField("de");
            System.out.println(field.getType());

            Class cls = field.getType();
            Field f = cls.getField("X1");
            Annotation a = f.getAnnotation(Desc.class);
            Method[] methods = a.getClass().getMethods();

            System.out.println(a);

            for (Method method : methods) {
                if (method.getName().equals("value")) {
                    System.out.println("**************find************");
                    try {
                        Object val = method.invoke(a, new Object[0]);
                        System.out.println("value: " + val);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }*/
        ///////////////////////////////////////////////////////////////
        //
        ///////////////////////////////////////////////////////////////

        /*try {
            Annotation[] a =
                mt.getClass().getMethod("testMethod").getAnnotations();
            for (int i = 0 ; i < a.length ; i++) {
                System.out.println("a[" + i + "]" + a[i]);
            }

        } catch (NoSuchMethodException e) {
            System.out.println(e);
        }
        String id = "1";
        System.out.println(id == "" ? "" : "2");

        Annotation ab = mt.getClass().getAnnotation(ID.class);
        System.out.println(ab);
        System.out.println("11");
        Field[] f = mt.getClass().getFields();
        System.out.println("22");
        Annotation a = f[0].getAnnotation(Java.class);
        Method[] methods = a.getClass().getMethods();
        System.out.println("num : " + methods.length);

        for (Method i : methods) {Type
            System.out.println("method = " + i.getName());
            //System.out.println("methods : " + i);

            if (i.getName().equals("value")) {
                System.out.println("**************find************");
                try {
                    Object val = i.invoke(a, new Object[0]);
                    System.out.println("value: " + val);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        System.out.println(a.toString()) ;
        System.out.println(a.value());

        Package p = mt.getClass().getPackage();
        System.out.println("aaa : " + p);
        try {
            Field field = mt.getClass().getField("a");
            System.out.println(field.getType());
            if (field.getType() == String.class) {
                System.out.println("equals to String");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } */

 

    }
}

 

'java core' 카테고리의 다른 글

java 5.0 enum.  (0) 2005.05.12
jdk 5.0 static import test code  (0) 2005.05.11
jdk 5.0 Annotation Test Code  (0) 2005.05.11
[펌] RMI(Remote Method Invocation)  (0) 2005.05.11
jdk 5.0) In runtime, java compile.  (0) 2005.04.25
Posted by '김용환'
,

자바 5.0의 Annotation에 대한 샘플 예제를 만들어 보았다.

 

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

@Retention(RetentionPolicy.RUNTIME)
@interface Title {
    String value();
}
public class AnnotationTest {

    public enum DescEnum {  @Title("1") X1,  X2 , X3 };
    public static EnumSet<DescEnum> de = EnumSet.of(DescEnum.X1, DescEnum.X2);

    public static void main(String[] args) {
        AnnotationTest mt = new AnnotationTest();
        ///////////////////////////////////////////////////////////////
        // EnumSet
        ///////////////////////////////////////////////////////////////

        try {
            Field field = mt.getClass().getField("de");
            System.out.println(field.getGenericType()) ;
            ParameterizedType tv = (ParameterizedType) field.getGenericType();
            System.out.println(tv);
            System.out.println("rawtype : " + tv.getRawType());
            System.out.println("getOwnerType : " + tv.getOwnerType());
            System.out.println("getReal : " + tv.getActualTypeArguments());

            for (Type t : tv.getActualTypeArguments()) {
                System.out.println("t : " + t);
                //System.out.println("class name: " + c.getName());
                Field[] enumFields = ((Class)t).getFields();
                for (Field f : enumFields) {
                    System.out.println("enum element name : " + f.getName());
                }
            }

            Iterator iter = de.iterator();
            while(iter.hasNext()) {
                System.out.println(iter.next());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

실행결과

 

$ java AnnotationTest
java.util.EnumSet<AnnotationTest$DescEnum>
java.util.EnumSet<AnnotationTest$DescEnum>
rawtype : class java.util.EnumSet
getOwnerType : null
getReal : [Ljava.lang.reflect.Type;@66848c
t : class AnnotationTest$DescEnum
enum element name : X1
enum element name : X2
enum element name : X3
X1
X2

 

'java core' 카테고리의 다른 글

jdk 5.0 static import test code  (0) 2005.05.11
jdk 5.0 Annotation, Enum Test code  (0) 2005.05.11
[펌] RMI(Remote Method Invocation)  (0) 2005.05.11
jdk 5.0) In runtime, java compile.  (0) 2005.04.25
jar  (0) 2005.04.25
Posted by '김용환'
,

▣ RMI(Remote Method Invocation)
   - 분산 시스템 구축시 Socket 방식을 이용하는 것보다 간결하고 신속함
   - RPC(Remote Procedure Call) : 원격지의 함수 호출, C 언어에서 사용
   - CORBA의 분산 객체 시스템과 비슷(이기종 간의 분산 처리 구축, 코바서버를 2중으로 구축시 모든 서버에서 트랜잭션이 안정적으로 진행이 안됨)
   - 원리
                       Client Area ↓                ↓Server Area 
     -----------------------------------------------------------------------------------------
     Local System --> Class --> Stub --> NETWORK --> Stub --> Skeleton --> Class Remote System
                   결과전송 <-- Stub <-- NETWORK <----------- Skeleton <-- 비지니스 로직 처리                

 


1. RMI 프로그래밍 순서도
   ① 원격 인터페이스 정의
   ② 원격 객체 구현
   ③ javac 컴파일 - 원격 객체 클래스
   ④ rmic - Stub, Skeleton class 생성
   ⑤ 로컬 객체 클래스 제작  
   ⑤ RMI 등록 서버 실행
   ⑥ 클라이언트 접속

 


2. UnicastRemoteObject 의 상속 구조

     public abstract class RemoteObject extends Object implements Remote, Serializable
     --> java.lang.Object 클래스의 hashCode(), equals(), toString() 메소드를 구현해서 갖고 있는 클래스
     ↑
     public abstract class RemoteServer extends RemoteObject
     --> 원격지 메소드 참조에 대한 구현에 대한 FrameWork을 갖고 있는 최상위 클래스
     ↑
     public class UnicastRemoteObject extends RemoteServer
     -->  tcp 상에서 object reference를 참조할 수 있도록 지원해 주는 클래스

 


3. Echo 예제 실습
--------------------------------------------------------------------------
구분  CLIENT SIDE SERVER SIDE
--------------------------------------------------------------------------
Interface            Echo.class  Echo.class

Remote Object   EchoImpl.class

Proxy  EchoImpl_Stub.class EchoImpl_Stub/Skel.class

Run Class            EchoClient.class EchoServer.class
--------------------------------------------------------------------------
실행 순서
1. rmic EchoImp
2. start rmiregistry   <-- C:\Program Files\Oracle\jre\1.1.7\bin; 경로가 PATH에 있으면 제거하고 시스템 재 시작합니다.
3. java EchoServer
4. java EchoClient nulunggi


------------------------ e.bat ------------------------
rmic EchoImpl
start rmiregistry
rem ---------
rem 서버 작동
rem ---------
java EchoServer

 

1/4-------------------------- Echo.java --------------------------
import java.rmi.RemoteException;

import java.rmi.Remote;

public interface Echo extends Remote{
  public String sayEcho(String name) throws RemoteException;
}


2/4-------------------------- EchoImpl.java --------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class EchoImpl extends UnicastRemoteObject implements Echo{
 String message;

 public EchoImpl() throws RemoteException{}

 public EchoImpl(String message) throws RemoteException{
  this.message = message;
 }

 public String sayEcho(String name){
  return "\n 엄기흥 강사 PC 로 부터 전송된 문자열 : " + message + " " + name + "님 \n";
 }
}
 

3/4-------------------------- EchoServer.java --------------------------
import java.rmi.Naming;

public class EchoServer{
  public static void main(String args[]){
    try{
      EchoImpl echoRef = new EchoImpl();
      Naming.bind("Echo",echoRef);
    }catch( java.rmi.AlreadyBoundException e){
      e.printStackTrace();  
    }catch(java.net.MalformedURLException e ){
      e.printStackTrace();
    }catch( java.rmi.RemoteException e){
      e.printStackTrace();   
    }
    System.out.println("--------------------------------");
    System.out.println("Echo RMI 서버가 작동 되었습니다.");
    System.out.println("--------------------------------");
  }
}


4/4-------------------------- EchoClient.java --------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;

public class EchoClient{
 public static void main(String args[]){
  String url = "rmi://127.0.0.1/Echo";
                     //String url = "rmi://" + args[0] + "/Echo";

  Echo echoRef = null;
  try{
   echoRef = (Echo)Naming.lookup(url);

   System.out.println(echoRef.sayEcho(args[0]));
  }catch(RemoteException e){
   e.printStackTrace();
  }catch(MalformedURLException e){
   e.printStackTrace();
  }catch(NotBoundException e){
   e.printStackTrace();
  }
  
 }
}

 


4. RMI 서버 모듈의 분리 예제
--------------------------------------------------------------------------
구분  CLIENT SIDE        SERVER SIDE
--------------------------------------------------------------------------
Interface            Echo.class         Echo.class
                      EchoFactory.class           EchoFactory.class

Remote Object          EchoImpl.class
                                                  EchoFactoryImpl.class 

Proxy  EchoImpl_Stub.class        EchoImpl_Stub/Skel.class
                     EchoFactoryImpl_Stub.class   EchoFactoryImpl_Stub/Skel.class

Run Class            EchoFactoryClient.class      EchoFactoryServer.class
Start File           s.bat                        r.bat
--------------------------------------------------------------------------


실행 방법 : r.bat
rem ---------------------------------------
rem 파일 내용 : Echo 예제 배치파일 입니다.
rem 작성일 : 2002-01-01
rem 작성자 : 엄기흥
rem ---------------------------------------
rmic EchoImpl
rmic EchoFactoryImpl
start rmiregistry.exe
java EchoFactoryServer

 


1/6------------------------ Echo.java ------------------------
import java.rmi.RemoteException;

import java.rmi.Remote;

public interface Echo extends Remote{
  public String sayEcho(String name) throws RemoteException;
}


2/6------------------------ EchoImpl.java ------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class EchoImpl extends UnicastRemoteObject implements Echo{
 String message;

 public EchoImpl() throws RemoteException{}

 public EchoImpl(String message) throws RemoteException{
  this.message = message;
 }

 public String sayEcho(String name){
  return "\n " + message + " " + name + "님 \n";
 }
}


3/6------------------------ EchoFactory.java ------------------------
import java.rmi.RemoteException;
import java.rmi.Remote;

public interface EchoFactory extends Remote{
  public Echo getEcho(String greeting) throws RemoteException;
}


4/6------------------------ EchoFactoryImpl.java ------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class EchoFactoryImpl extends UnicastRemoteObject implements EchoFactory{
 
  public EchoFactoryImpl() throws RemoteException{}

  public Echo getEcho(String message) throws RemoteException{
    EchoImpl echoRef = new EchoImpl(message);
    return (Echo)echoRef;
  }

}


5/6------------------------ EchoFactoryServer.java ------------------------
import java.rmi.Naming;

public class EchoFactoryServer {
 public static void main(String args[]) throws Exception{
  EchoFactoryImpl factoryRef = new EchoFactoryImpl();

  Naming.rebind("EchoFactory",factoryRef);
  
  System.out.println("서버가 시작되었습니다.");
 }
}


6/6------------------------ EchoFactoryClient.java ------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;

public class EchoFactoryClient{
  public static void main(String args[]){
   
 //String url = "rmi://127.0.0.1/EchoFactory";

 EchoFactory ref = null;

 try{
  if (args.length != 2){
                        System.out.println("파라미터가 잘못되었습니다.");
   System.out.println("사용법 : java EchoFactoryClient nulunggi 211.108.242.114");
   System.exit(1);
  }

  ref = (EchoFactory)Naming.lookup("rmi://" + args[1] + "/EchoFactory");

  Echo echoHello = ref.getEcho("수고하셨습니다.");
  Echo echoGood = ref.getEcho("2개월간 고생하셨습니다.");

  System.out.println(echoHello.sayEcho(args[0])); 
  System.out.println(echoGood.sayEcho(args[0])); 

 }catch(RemoteException e){
  e.printStackTrace();  
 }catch(MalformedURLException e){
  e.printStackTrace(); 
 }catch(NotBoundException e){
  e.printStackTrace(); 
 }

  }
}

 


▣ RMI + Thread를 이용하여 여러 컴퓨터에서 계산하기

------------------------ e.bat ------------------------
rmic EchoImpl
start rmiregistry
rem ---------
rem 서버 작동
rem ---------
java EchoServer

 


1. 서버쪽 수정 EchoImpl.java

1/4-------------------------- Echo.java --------------------------
import java.rmi.RemoteException;

import java.rmi.Remote;

public interface Echo extends Remote{
  public String sayEcho(String name) throws RemoteException;
}


2/4-------------------------- EchoImpl.java --------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class EchoImpl extends UnicastRemoteObject implements Echo{
 String message;

 public EchoImpl() throws RemoteException{}

 public EchoImpl(String message) throws RemoteException{
  this.message = message;
 }

 public String sayEcho(String name){

             int i=1;
             long hap=0;

             for(long q=1; q<=500000000; q++){
                       hap = hap + q;
             }
    return i + "번째 1부터 500,000,000까지의 합 : " + hap + "\n";

 }
}
 

3/4-------------------------- EchoServer.java --------------------------
import java.rmi.Naming;

public class EchoServer{
  public static void main(String args[]){
    try{
      EchoImpl echoRef = new EchoImpl();
      Naming.bind("Echo",echoRef);
    }catch( java.rmi.AlreadyBoundException e){
      e.printStackTrace();  
    }catch(java.net.MalformedURLException e ){
      e.printStackTrace();
    }catch( java.rmi.RemoteException e){
      e.printStackTrace();   
    }
    System.out.println("--------------------------------");
    System.out.println("Thread용 Echo RMI 서버가 작동 되었습니다.");
    System.out.println("--------------------------------");
  }
}


4/4-------------------------- EchoClient.java --------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;

public class EchoClient{
 public static void main(String args[]){
  String url = "rmi://127.0.0.1/Echo";
                     //String url = "rmi://" + args[0] + "/Echo";

  Echo echoRef = null;
  try{
   echoRef = (Echo)Naming.lookup(url);

   System.out.println(echoRef.sayEcho(args[0]));
  }catch(RemoteException e){
   e.printStackTrace();
  }catch(MalformedURLException e){
   e.printStackTrace();
  }catch(NotBoundException e){
   e.printStackTrace();
  }
  
 }
}

 

2. 클라이언트쪽
------------------------ EchoClientThread.java -------------------
/***********************************
파일명:
작성자: 엄기흥
최종 수정일: 20020308-2102
파일 내용: 자바 수업 중에 테스트 한 파일
************************************/
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;

public class EchoClientThread extends Thread{
 String ip=null;
 Echo echoRef = null;

 EchoClientThread(String ip){
     this.ip = ip;
 }

 public void run(){
  try{
   String url = "rmi://" + ip + "/Echo";
   echoRef = (Echo)Naming.lookup(url);
   System.out.println(echoRef.sayEcho("누룽지"));

  }catch(RemoteException e){
   e.printStackTrace();
  }catch(MalformedURLException e){
   e.printStackTrace();
  }catch(NotBoundException e){
   e.printStackTrace();
  }

 }

 public static void main(String args[]){
  EchoClientThread e67, e74, e76, e78, e98, e72, e69;
  

  e67 = new EchoClientThread("211.108.242.106");
  e74 = new EchoClientThread("211.108.242.107");
  e76 = new EchoClientThread("211.108.242.109");
  e78 = new EchoClientThread("211.108.242.110");
  e98 = new EchoClientThread("211.108.242.108");
  e72 = new EchoClientThread("211.108.242.112");
  e69 = new EchoClientThread("211.108.242.114");

  e67.start();
  e74.start();
  e76.start();
  e78.start();
  e98.start();
  e72.start();
  e69.start();
 }
}

 

------------------------ EchoClientThread1.java -------------------
/***********************************
파일명:
작성자: 엄기흥
최종 수정일: 20020308-2102
파일 내용: 자바 수업 중에 테스트 한 파일
************************************/
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;

public class EchoClientThread1 extends Thread{
 String ip=null;
 Echo echoRef = null;
 
 EchoClientThread1(String ip){
     this.ip = ip;
 }

 public void run(){
  try{
   if(ip.equals("67")){
    String url = "rmi://211.108.242.114/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("74")){
    String url = "rmi://211.108.242.106/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("76")){
    String url = "rmi://211.108.242.107/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("78")){
    String url = "rmi://211.108.242.109/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("98")){
    String url = "rmi://211.108.242.110/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("72")){
    String url = "rmi://211.108.242.111/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }else if(ip.equals("69")){
    String url = "rmi://211.108.242.112/Echo";
    echoRef = (Echo)Naming.lookup(url);
    System.out.println(echoRef.sayEcho("누룽지"));
   }

  }catch(RemoteException e){
   e.printStackTrace();
  }catch(MalformedURLException e){
   e.printStackTrace();
  }catch(NotBoundException e){
   e.printStackTrace();
  }

 }

 public static void main(String args[]){
  EchoClientThread1 e67, e74, e76, e78, e98, e72, e69;
  

  e67 = new EchoClientThread1("67");
  e74 = new EchoClientThread1("74");
  e76 = new EchoClientThread1("76");
  e78 = new EchoClientThread1("78");
  e98 = new EchoClientThread1("98");
  e72 = new EchoClientThread1("72");
  e69 = new EchoClientThread1("69");

  e67.start();
  e74.start();
  e76.start();
  e78.start();
  e98.start();
  e72.start();
  e69.start();
 }
}

'java core' 카테고리의 다른 글

jdk 5.0 Annotation, Enum Test code  (0) 2005.05.11
jdk 5.0 Annotation Test Code  (0) 2005.05.11
jdk 5.0) In runtime, java compile.  (0) 2005.04.25
jar  (0) 2005.04.25
Runtime in jdk5.0  (0) 2005.03.26
Posted by '김용환'
,

인터냇에서 찾은 미국사람의 싸이트에서 수정을 하고, 올린 글임..

제대로 컴파일되게 했다..

 

시간을 이용하여, 파일을 만들고. 그 파일을 실시간으로 컴파일하는 샘플 예제이다.

 

import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import com.sun.tools.javac.Main;

 

/**

 * author @knight

 */

public class MakeTodayClass {
  Date today = new Date();
  String todayMillis = Long.toString(today.getTime());
  String todayClass = "z_" + todayMillis;
  String todaySource = todayClass + ".java";

  public static void main (String args[]){
    MakeTodayClass mtc = new MakeTodayClass();
    mtc.createIt();
    if (mtc.compileIt()) {
       System.out.println("Running " + mtc.todayClass + ":\n\n");
       mtc.runIt();
       }
    else
       System.out.println(mtc.todaySource + " is bad.");
    }

  public void createIt() {
    try {
      FileWriter aWriter = new FileWriter(todaySource, true);
      aWriter.write("public class "+ todayClass + "{");
      aWriter.write(" public void print() {");
      aWriter.write(" System.out.println(\""+todayMillis+"\");");
      aWriter.write(" }}\n");
      aWriter.flush();
      aWriter.close();
      }
    catch(Exception e){
      e.printStackTrace();
      }
    }

  public boolean compileIt() {
      try {
        String [] source = { new String(todaySource)};
        com.sun.tools.javac.Main main = new com.sun.tools.javac.Main();
        main.compile(source);
      }  catch (Exception e) {
          e.printStackTrace();
          return false;
      }
    return true;
    }

  public void runIt() {
    try {
      Class params[] = {};
      Object paramsObj[] = {};
      Class thisClass = Class.forName(todayClass);
      Object iClass = thisClass.newInstance();
      Method thisMethod = thisClass.getDeclaredMethod("print", params);
      thisMethod.invoke(iClass, paramsObj);
      }
    catch (Exception e) {
      e.printStackTrace();
      }
    }
 }

'java core' 카테고리의 다른 글

jdk 5.0 Annotation Test Code  (0) 2005.05.11
[펌] RMI(Remote Method Invocation)  (0) 2005.05.11
jar  (0) 2005.04.25
Runtime in jdk5.0  (0) 2005.03.26
Annotation  (0) 2005.03.18
Posted by '김용환'
,

jar

java core 2005. 4. 25. 09:55
JAR 파일
JAR 파일 포맷의 힘

Level: Introductory

Pagadala J. Suresh, 소프트웨어 엔지니어, IBM Global Services India
Palaniyappan Thiagarajan, 소프트웨어 엔지니어, IBM Global Services India

2003년 10월 9일

대부분의 자바 프로그래머들은 JAR 파일의 기본 작동에 익숙하다. 하지만 JAR 파일 포맷의 막강한 힘을 아는 개발자는 드물다.

JAR 파일
JAR 파일 포맷은 대중적인 ZIP 파일 포맷을 근간으로 하여 많은 파일들을 하나로 모으는데 사용된다. ZIP 파일과는 달리 JAR 파일은 압축과 디스트리뷰션 뿐만 아니라 라이브러리, 컴포넌트, 플러그인 등의 전개와 캡슐화에도 사용되며 컴파일러나 JVM 같은 툴이 직접 사용하기도 한다. 전개 디스크립터 같이 JAR에 포함된 특별한 파일은 특정 JAR가 취급되는 방법을 툴에 지시한다.

JAR 파일은 다음과 같은 데에 사용된다:

  • 클래스 라이브러리의 분배 및 사용
  • 애플리케이션과 확장용 블록 구현
  • 컴포넌트, 애플릿, 플러그인용 전개 유닛
  • 컴포넌트와 관련된 보조 리소스 패키지

JAR 파일 포맷은 많은 혜택과 기능을 제공하며 ZIP 또는 TAR 같은 전통적인 아카이브 포맷이 줄 수 없는 많은 것들을 제공한다. 이를 테면:

  • 보안. JAR 파일의 내용을 디지틀 방식으로 서명할 수 있다.

  • 다운로드 시간 감소. 애플릿이 JAR 파일로 번들되면 이 애플릿의 클래스 파일과 관련 리소스들은 한 번의 HTTP 트랜잭션에서 브라우저를 통해 다운로드 될 수 있다.

  • 압축. JAR 포맷은 파일의 효율적인 저장을 위해 압축시킨다.

  • 투명한 플랫폼 확장. Java Extensions Framework은 자바 핵심 플랫폼에 기능을 추가할 수 있는 수단을 제공하는데 이 때, 확장의 패키지에 JAR 파일을 사용한다. (Java 3D와 JavaMail이 Sun에서 개발된 확장의 예이다.)

  • 패키지 실링(sealing). JAR 파일에 저장된 패키지는 선택적으로 봉합(seal)되어 버전의 영속성과 보안을 강화할 수 있다. 패키지 봉합은 이 패키지에 정의된 모든 클래스들이 같은 JAR 파일에서 찾을 수 있어야 함을 의미한다.

  • 패키지 버저닝(versioning). JAR 파일은 이것이 포함하고 있는 파일 관련 데이터를 보유하고 있다. 벤더와 버전 정보 등이다.

  • 이식성(Portability). JAR 파일을 핸들링하는 메커니즘은 자바 플랫폼의 핵심 API의 표준의 일부이다.

JAR의 압축과 압축풀기
jar 툴(jar 참조)은 파일을 기본적으로 압축한다. 압축이 풀린 JAR 파일은 압축된 JAR 파일 보다 더 빠르게 로딩될 수 있다. 로딩 시간 동안 파일의 압축 풀기 시간이 줄어들기 때문이다. 하지만 네트워크를 통한 다운로드 시간은 압축이 풀린 파일이 더 길다.

META-INF 디렉토리
대부분의 JAR 파일에는 META-INF 디렉토리가 포함되어 있는데 이는 패키지의 저장과 보안 및 버저닝 정보 같은 확장 설정 데이터를 저장하는데 사용된다. META-INF 디렉토리의 파일과 디렉토리는 Java2platform에서 인식 및 인터프리팅되어 애플리케이션, 확장, 클래스 로더를 설정한다:

  • MANIFEST.MF. manifest 파일은 확장 관련, 패키지 관련 데이터를 정의한다.

  • INDEX.LIST. 이 파일은 jar 툴의 새로운 -i 옵션에 의해 생성되어 애플리케이션 또는 확장에 정의된 패키지의 위치 정보를 포함한다. 이것은 JarIndex 구현의 일부이고 클래스 로더에 의해 사용되어 클래스 로딩 프로세스의 속도를 높인다.

  • xxx.SF. JAR 파일의 서명 파일이다. xxx는 서명자를 나타낸다.

  • xxx.DSA. 서명 파일과 관련된 서명 블록 파일은 JAR 파일의 서명에 사용된 공식 서명을 저장한다.

jar 툴
JAR 파일로 기본적인 태스크를 수행하려면 자바 개발 킷의 일부로 제공되는 Java Archive Tool (jar 툴)을 사용한다. jar 툴을 jar 명령어로 호출한다. 표 1은 일반 애플리케이션이다:

표 1. jar 툴의 일반적인 사용

기능 명령어
개별 파일에서 JAR 파일 만들기 jar cf jar-file input-file...
디렉토리에서 JAR 파일 만들기 jar cf jar-file dir-name
압축 풀린 JAR 파일 만들기 jar cf0 jar-file dir-name
JAR 파일 업데이트 jar uf jar-file input-file...
JAR 파일 내용보기 jar tf jar-file
JAR 파일 내용 추출하기 jar xf jar-file
JAR 파일에서 특정 파일 추출하기 jar xf jar-file archived-file...
실행 JAR 파일로 패키지된 애플리케이션 실행하기 java -jar app.jar

실행 JAR 파일
실행 JAR 파일은 특별히 설정된 JAR 파일에 저장된 독립적인 자바 애플리케이션이다. 파일을 추출하거나 클래스 경로를 설정하지 않고 JVM에 의해 직접 실행될 수 있다. 비 실행 JAR에 저장된 애플리케이션을 구동하려면 이를 클래스 경로에 추가하고 애플리케이션의 메인 클래스를 이름별로 호출해야한다. 하지만 실행 JAR 파일을 사용하면 이를 추출하거나 메인 엔트리 포인트를 알 필요 없이 애플리케이션을 실행할 수 있다.

실행 JAR 파일 만들기
실행 JAR 파일을 만들기는 쉽다. 모든 애플리케이션 코드를 하나의 디렉토리에 놓는 것으로 시작한다. 애플리케이션의 메인 클래스가 com.mycompany.myapp.Sample이라고 가정해보자. 애플리케이션 코드를 포함하고 메인 클래스를 구분하는 JAR 파일 생성이 필요하다. 이를 위해 라는 manifest 파일을 어딘가에(애플리케이션 디렉토리는 아니다) 만들고 여기에 다음 행을 추가한다:


Main-Class: com.mycompany.myapp.Sample

그런 다음 JAR 파일을 다음과 같이 만든다:


jar cmf manifest ExecutableJar.jar application-dir

이제 JAR 파일인 ExecutableJar.jar가 java -jar를 사용하여 실행될 수 있다.

실행 JAR 파일 시작하기
애플리케이션을 ExecutableJar.jar라는 실행 JAR 파일로 묶었으므로 다음 명령어를 사용하여 파일에서 직접 애플리케이션을 시작할 수 있다:


java -jar ExecutableJar.jar

패키지 실링(sealing)
JAR 파일안에 패키지를 봉합(sealing)한다는 것은 이 패키지에 정의된 모든 클래스가 같은 JAR 파일에서 찾아져야 한다는 것을 의미한다. 이로서 패키지 작성자는 패키지된 클래스들의 버전 영속성을 강화할 수 있다. 봉합은 보안 조치도 제공하여 코드 탬퍼링을 탐지한다.

패키지를 봉합하려면 패키지용 Name 헤더를 추가한다. 그 뒤에 Sealed 헤더 값을 JAR manifest 파일에 대해 "true"로 한다. 실행 JAR 파일과 마찬가지로 manifest 파일을 적절한 헤더 엘리먼트로 지정하여 JAR를 봉합할 수 있다:


Name: com/samplePackage/
Sealed: true

Name 헤더는 패키지의 관련 경로명을 정한다. 파일이름과 구별되도록 "/"로 끝난다. Name 헤더에 뒤따르는 모든 헤더는 공백 라인 없이 Name 헤더에 지정된 파일이나 패키지에 붙는다. 위 예제에서 Sealed 헤더가 공백 라인 없이 Name 헤더 다음에 발생했기 때문에 Sealed 헤더는 com/samplePackage 패키지에만 붙는것으로 인터프리팅된다.

JAR 파일 외에 다른 소스에서 봉합된 패키지의 클래스를 로딩하려고 하면 JVM이 SecurityException을 던진다.

확장 패키징
확장은 자바 플랫폼에 기능을 추가한다. 확장 메커니즘은 JAR 파일 포맷에 구현된다. 확장 메커니즘으로 JAR 파일이 다른 필요한 JAR 파일들을 Class-Path 헤더를 통해 manifest 파일에 지정할 수 있다.

extension1.jar와 extension2.jar가 같은 디렉토리 안의 두 개의 JAR 파일에 있다고 가정해보자. extension1.jar의 manifest는 다음 헤더를 포함하고 있다:


Class-Path: extension2.jar

이 헤더는 extension2.jar의 클래스들이 extension1.jar의 클래스를 목표에 맞춘 확장 클래스로서 작용한다는 것을 나타내고 있다. extension1.jar의 클래스들은 extension2.jar가 클랫의 경로의 일부가 될 필요 없이 extension2.jar의 클래스를 호출할 수 있다.

JVM은 확장 메커니즘을 사용하는 JAR를 로딩할 때 Class-Path 헤더에 레퍼런스된 JAR를 클래스 경로에 자동으로 추가한다. 하지만, 확장 JAR 경로는 관련 경로로 인터프리팅되어 일반적으로 확장 JAR는 이를 레퍼런싱하는 JAR로서 같은 디렉토리에 저장되어야 한다.

예를 들어 ExtensionDemo 클래스를 레퍼런싱하는 ExtensionClient 클래스가 ExtensionClient.jar라고 하는 JAR 파일에 번들되었고 ExtensionDemo 클래스가 ExtensionDemo.jar에 번들되었다고 가정해보자. ExtensionDemo.jar가 확장으로 취급되기 위해서는 ExtensionDemo.jar는 ExtensionClient.jar의 manifest 안의 Class-Path 헤더에 리스트되어야 한다:


Manifest-Version: 1.0
Class-Path: ExtensionDemo.jar

Class-Path 헤더의 값은 경로가 지정이 안된 ExtensionDemo.jar 이며 ExtensionDemo.jar가 ExtensionClient JAR 파일과 같은 디렉토리에 위치해 있음을 나타내고 있다.

JAR 파일의 보안
JAR 파일은 jarsigner 툴을 사용하거나 java.security API를 통해서 직접 서명될 수 있다. 서명된 JAR 파일은 원래 JAR 파일과 정확히 같다. manifest만이 업데이트 된 것과 두 개의 추가 파일들이 META-INF 디렉토리에 추가된 것을 제외하고.

Keystore 데이터베이스에 저장된 인증을 사용하여 JAR 파일은 서명된다. Keystore에 저장된 인증은 패스워드로 보호된다.

그림 1. Keystore 데이터베이스
Keystore Database

JAR의 각 서명자는 JAR 파일의 META-INF 디렉토리안에 있는 .SF 확장자가 붙은 서명으로 표현된다. 이 파일의 포맷은 manifest 파일과 비슷하다. 메인 섹션과 개별 엔트리들로 구성되어 있다. 서명된 JAR에서 오는 파일을 확인하기 위해 서명 파일의 다이제스트 값은 JAR 파일의 상응 엔트리에 대비하여 계산된 다이제스트와 비교된다.

Listing 1. Manifest와 서명 파일

Contents of signature file META-INF/MANIFEST.MF

Manifest-Version: 1.0
Created-By: 1.3.0 (Sun Microsystems Inc.)

Name: Sample.java
SHA1-Digest: 3+DdYW8INICtyG8ZarHlFxX0W6g=

Name: Sample.class
SHA1-Digest: YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=

Contents of signature file META-INF/JAMES.SF

Signature-Version: 1.0
SHA1-Digest-Manifest: HBstZOJBuuTJ6QMIdB90T8sjaOM=
Created-By: 1.3.0 (Sun Microsystems Inc.)

Name: Sample.java
SHA1-Digest: qipMDrkurQcKwnyIlI3Jtrnia8Q=

Name: Sample.class
SHA1-Digest: pT2DYby8QXPcCzv2NwpLxd8p4G4=

디지틀 서명
디지틀 서명은 .SF 서명 파일의 서명완료된 버전이다. 디지틀 서명 파일은 바이너리 파일이며 .SF 파일과 같은 파일이름을 갖고 있지만 다른 확장이다. 확장은 디지틀 서명 유형에 따라 다양하고 (RSA, DSA, PGP). JAR 서명에 사용된 인증 유형에 따라 다르다.

Keystore
JAR 파일에 서명하려면 프라이빗 키를 가져야 한다. 프라이빗 키와 관련 퍼블릭 키 인증은 패스워드로 보호된 데이터베이스(keystores)에 저장된다. JDK는 Keystore를 구현 및 변경하는 툴을 포함하고 있다. Keystore의 각 키는 앨리어스에 의해 구분되는데 전형적으로 키를 소유한 서명자의 이름이다.

모든 Keystore 엔트리들은 고유 앨리어스로 액세스된다. 앨리어스는 Keystore에 엔터티를 추가할 때 keytool -genkey 명령어를 사용하여 지정되어 키 쌍을 만든다. 뒤따르는 keytool 명령어는 이와 같은 앨리어스를 사용하여 엔터티를 언급해야 한다.

예를 들어 "james"라는 앨리어스로 새로운 퍼블릭/프라이빗 키 쌍을 만들고 퍼블릭 키를 자가 서명된 인증으로 래핑하려면 다음 명령어를 사용한다:


keytool -genkey -alias james -keypass jamespass 
        -validity 80 -keystore jamesKeyStore 
        -storepass jamesKeyStorePass

jarsigner 툴
jarsigner 툴은 Keystore를 사용하여 JAR 파일에 대한 디지틀 서명을 만들거나 확인한다.

위 예제에서 처럼 "jamesKeyStore" Keystore를 만들었고 여기에 "james" 앨리어스와 키를 포함하고 있다고 가정해보자. 다음 명령어로 JAR 파일에 서명할 수 있다:


jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass 
          -keypass jamespass -signedjar SSample.jar Sample.jar james

이 명령어는 앨리어스가 "james"이고 패스워드가 "jamespass"인 키를 보내 Sample.jar 파일에 서명하고 SSample.jar라는 서명된 JAR를 만든다.

jarsigner 툴은 서명된 JAR 파일을 확인할 수 있다. 이 작동은 JAR 파일을 서명하는 것 보다 훨씬 쉽다. 다음 명령어를 실행하면 된다:


jarsigner -verify SSample.jar

JAR 인덱싱(indexing)
애플리케이션 또는 애플릿이 다중의 JAR 파일들로 번들된다면 클래스 로더는 단순한 리니어 검색 알고리즘을 사용하여 클래스 경로의 엘리먼트를 검색한다. 클래스 로더가 존재하지 않은 리소스를 찾으려고 하면 애플리케이션 또는 애플릿 내의 모든 JAR 파일들은 다운로드 되어야한다. 큰 네트워크 애플리케이션과 애플릿의 경우 늦은 시작, 지연된 응답, 네트워크 대역 낭비를 초래한다.

JDK 1.3 이후 JAR 파일 포맷은 인덱싱(indexing)을 지원하여 네트워크 애플리케이션(특히 애플릿)의 클래스 검색 프로세스를 최적화했다. JarIndex 메커니즘은 애플릿 또는 애플리케이션에 정의된 모든 JAR 파일의 내용을 모아 첫 번째 JAR 파일의 인덱스 파일에 이 정보를 저장한다. 첫 번째 JAR 파일이 다운로드된 후에 애플릿 클래스 로더는 모아진 콘텐트 정보를 사용하여 JAR 파일을 효율적으로 다운로드한다. 이 디렉토리 정보는 INDEX.LIST라는 이름으로 간단한 텍스트 파일로 저장된다.(META-INF 디렉토리).

JarIndex 만들기

그림 2. JarIndex
JarIndex Demo

다음 명령어를 사용하여 JarIndex_Main.jar, JarIndex_test.jar, JarIndex_test1.jar용 인덱스 파일을 만든다:


jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar 

INDEX.LIST 파일은 간단한 포맷을 갖고 있으며 색인된 JAR 파일에 저장된 패키지 또는 클래스 이름을 포함하고 있다.(Listing 2):

Listing 2. JarIndex INDEX.LIST 파일

JarIndex-Version: 1.0

JarIndex_Main.jar
sp

JarIndex_test.jar
Sample

SampleDir/JarIndex_test1.jar
org
org/apache
org/apache/xerces
org/apache/xerces/framework
org/apache/xerces/framework/xml4j

참고자료

'java core' 카테고리의 다른 글

[펌] RMI(Remote Method Invocation)  (0) 2005.05.11
jdk 5.0) In runtime, java compile.  (0) 2005.04.25
Runtime in jdk5.0  (0) 2005.03.26
Annotation  (0) 2005.03.18
Java condition variable  (0) 2005.02.18
Posted by '김용환'
,

Runtime in jdk5.0

java core 2005. 3. 26. 04:12
Author Topic: command execution error
Marina JOSEPH
greenhorn
Member # 67293

posted March 02, 2004 01:59 AM      Profile for Marina JOSEPH   Email Marina JOSEPH   Send New Private Message      Edit/Delete Post  Reply With Quote 
import java.io.*;

class cmdEx
{
public static void main(String[] arg)
{
String str;
Process p;
BufferedReader in;
try
{
p = Runtime.getRuntime().exec("/bin/ls -aFl");
in = new BufferedReader(new InputStreamReader(p.getInputStream()));

while ((str = in.readLine()) != null)
{
System.out.println(str);
}
}
catch (IOException e)
{ System.out.println(e.toString()); }
}

}
message
c:\>java cmdEx
Error
java.io.IOException :CreateProcess :/bin/ls-aFl error=3

this can run p=Runtime.getRuntime().exec("java"); its working


but p=Runtime.getRuntime().exec("dir /p"); from windows.
again display the error
java.io.IOException :CreateProcess ir /p error=3


Posts: 18 | Registered: Feb 2004  |  IP: Logged
Corneil du Plessis
greenhorn
Member # 66649

posted March 02, 2004 03:59 AM      Profile for Corneil du Plessis   Email Corneil du Plessis   Send New Private Message      Edit/Delete Post  Reply With Quote 
In Windows you will have to use Runtime.getRuntime().exec("cmd /c dir /s")
The process you want to envoke is the standard command processor. You will notice in JDK 1.5 that System.getEnv is not deprecated anymore. It will allow you to do Runtime.getRuntime().exec(System.getEnv("ComSpec") + " /c dir /s") which will work on all Windows platforms, because you will find that cmd.exe is not available on all platforms.

Posts: 11 | Registered: Feb 2004  |  IP: Logged
Ernest Friedman-Hill
sheriff and author
Member # 52711

posted March 02, 2004 04:00 AM      Profile for Ernest Friedman-Hill   Author's Homepage   Email Ernest Friedman-Hill   Send New Private Message      Edit/Delete Post  Reply With Quote 
The UNIX code should work fine. Be sure there's really a /bin/ls on your system, and that it really accepts the flags you're giving it.

For the Windows "dir" version, note that "dir" is not a separate program, but a command implemented by cmd.exe (or command.com). I believe you need to execute something like

cmd /e "dir /p"

rather than just "dir /p".

Note that this exeact issue is covered in the Java programmer's FAQ.

--------------------

[Jess in Action] [Weblog]


Posts: 7082 | Registered: Jul 2003  |  IP: Logged
Tim Holloway
bartender
Member # 15625

posted March 02, 2004 09:16 AM      Profile for Tim Holloway   Author's Homepage   Email Tim Holloway   Send New Private Message      Edit/Delete Post  Reply With Quote 
However this is a horrible way to get a list of files for processing. Use the java.io.File.list() method instead. You can add a filter if you like to do the equivalent of wildcards.

Hint: You can normalize filenames to the Unix style: C:\java\myfile.txt can also be accessed in java code (or most config files) as C:/java/myfile.txt.

And that way you don't get burned by forgetting that a backslash is an escape character!

--------------------

If you extend the currently popular business philosophy to its ultimate end, we'll end up with apps produced in no time, for no cost that do nothing. And from the way some major corporate sites work, it won't be much longer.


Posts: 2800 | Registered: Jun 2001  |  IP: Logged
Ernest Friedman-Hill
sheriff and author
Member # 52711

posted March 02, 2004 09:46 AM      Profile for Ernest Friedman-Hill   Author's Homepage   Email Ernest Friedman-Hill   Send New Private Message      Edit/Delete Post  Reply With Quote 
quote:
Originally posted by Tim Holloway:
However this is a horrible way to get a list of files for processing.

I agree, but based on her other posts, she's implementing something like a homegrown rexec service; I think executing the commands is the whole point.

[ March 02, 2004: Message edited by: Ernest Friedman-Hill ]

--------------------

[Jess in Action] [Weblog]

'java core' 카테고리의 다른 글

jdk 5.0) In runtime, java compile.  (0) 2005.04.25
jar  (0) 2005.04.25
Annotation  (0) 2005.03.18
Java condition variable  (0) 2005.02.18
Threads from aritma  (0) 2005.02.12
Posted by '김용환'
,

Annotation

java core 2005. 3. 18. 05:26

Learn to Use the New Annotation Feature of Java 5.0

Developers have always struggled to find ways of adding semantic data to their Java code. They had to: Java didn't have a native metadata facility. But that's all changed with version 5.0 of Java, which allows annotations as a typed part of the language. 
he new Java 2 Platform Standard Edition 5.0 (the developer version number is 1.5 and the code name is "Tiger") provides many new features, among them is the ability to annotate Java program elements and to create custom annotation types. Development and deployment tools can then read annotated data (also known as metadata) and process it in some fashion.

Previous versions of Java provided a limited and ad-hoc mechanism for annotating code through JavaDoc comments and keyword modifiers. Tools such as XDoclet provide a slightly more sophisticated, yet non-standard annotation syntax, which piggybacks on top of JavaDoc. But now, with Java 1.5, annotations are a typed part of the Java language and allow for both runtime and compile-time processing of annotation data.

What Are Annotations?
In short, annotations are metadata or data about data. Annotations are said to annotate a Java element. An annotation indicates that the declared element should be processed in some special way by a compiler, development tool, deployment tool, or during runtime.

Older versions of Java have rough-and-ready annotation functionality. A good example is the @deprecated JavaDoc tag. The @deprecated tag is used for more than sheer documentation purposes. This tag has no effect on the code it describes, but causes the compiler to produce warnings if any other code references the tagged element. JavaDoc does not seem to be the proper place for this type of metadata, but there was no other annotation facility in previous versions of Java. With Java 1.5, finally, annotations are a typed part of the language and the version even comes with some with pre-built annotations, one of which can be used to mark a class as deprecated (I'll cover this later).

The code below shows how you can declare a method that uses an annotation. It is one of Java 1.5's built-in annotation types:


class Child extends Parent {
    @Overrides
    public void doWork() {
        //do something      
    }
}
In the code above, note that the annotation starts with an "at" (@) sign. This annotation takes no parameters and is merely used to mark a method for some purpose. It is therefore called a marker annotation. There are also normal annotations and single member annotations (more on these later).

Annotations types are blueprints for annotations, similar to how a class is the blueprint for an object. You can create your own custom annotations by defining annotation types.

The code below shows the declaration of a normal annotation type:


public @interface MyAnnotationType {
    int someValue();
    String someOtherValue();
}
Annotations can be analyzed statically before and during compile time. Annotations will likely be used before compile time mainly to generate supporting classes or configuration files. For example, a code generator (XDoclet, for example) can use annotation data in an EJB implementation class to generate EJB interfaces and deployment descriptors for you, reducing both your effort and the error rate. The average developer will probably not be writing code-generation tools, so these annotation types are likely to be used out-of-the-box rather than authored anew.

Author's Note:

Annotations will also be used for compile-time checking such as to produce warnings and errors for different failure scenarios. An example of an annotation that is used at compile time is the new @Deprecated annotation, which acts the same as the old @deprecated JavaDoc tag. Of course, a compiler has to know how to interpret annotation data that is meant to produce compile-time warnings, so again, annotations that do things at compile time will likely be used frequently, but rarely written by average developers.

Annotations can be useful at runtime as well. Using annotations you could mark code to behave in a particular way whenever it is called. For example, you could mark some methods with a @prelog annotation. Then at runtime, you could analyze the methods that you're calling and print a particular log message before you begin executing code for that method. One way to achieve this would be through the use of the updated Java 1.5 reflection API. The reflection API now provides access to runtime-accessible annotation data.

< Another way to use annotations at runtime is to use Aspect-Oriented Programming (AOP). AOP uses pointcuts—sets of points configured to executed aspects. You could define a pointcut that will execute an aspect for an annotated method. My guess is that developers would be more likely to write their own runtime annotation types than they would annotation types used for code generation and compile-time checking. Still, writing and understanding the code that accesses the annotations (the annotation consumer) at runtime is fairly advanced.



Annotating Code
Annotations fall into three categories: normal annotations, single member annotations, and marker annotations (see Table 1). Normal and single member annotations can take member values as arguments when you annotate your code.

Category Example
Normal Annotations—Annotations that take multiple arguments. The syntax for these annotations provides the ability to pass in data for all the members defined in an annotation type. @MyNormalAnnotation(mem1="val1", mem2="val2") public void someMethod() { ... }
Single Member Annotations—An annotation that only takes a single argument has a more compact syntax. You don't need to provide the member name. @MySingleMemberAnnotation("a single value") public class SomeClass { ... }
Marker Annotations—These annotations take no parameters. They are used to mark a Java element to be processed in a particular way. @Deprecated public void doWork() { ... }

Any Java declaration can be marked with an annotation. That is, an annotation can be used on a: package, class, interface, field, method, parameter, constructor, enum (newly available in Java 1.5), or local variable. An annotation can even annotate another annotation. Such annotations are called meta-annotations.

This code below shows an annotated class, constructor, field, and method.


@ClassLevelAnnotation(arg1="val1", arg2={"arg2.val1","arg2.val2"})
public class AnnotationExample {

    @FieldLevelAnnotation()
    public String field;    

    @CtorLevelAnnotation()
    public AnnotationsTest() {
        // code
    }

    @MethodLevelAnnotationA("val")
    @MethodLevelAnnotationB(arg1="val1",arg2="val2")
    public void someMethod(String string) {
        // code
    }    
}
As you can see in the ClassLevelAnnotation, annotations may also take arrays of values. When creating an annotation that requires an array you must surround the array of parameters with brackets ( { … } ) and you must comma-separate each array parameter.

Annotation types may define default values for some members. Every member-value pair that does not have a default value must be supplied when you create an annotation.

The annotation-type declaration below uses meta-annotations, which provide information on how the annotation type can be used:


@Retention(RUNTIME) 
@Target(METHOD)
public @interface MyAnnotationType {
    String value;
}
This code shows how to use meta-annotations when declaring your own annotation type. I will cover the specifics on declaring annotation types and meta-annotation types later, but for now, just know that you can use meta-annotations to annotate other annotations.

Packages annotations are also allowed, but because packages are not explicitly declared in Java, package annotations must be declared in a source file called package-info.java in the directory containing the source files for the package. This file should contain only a package declaration, preceded by any annotations that should apply to the package. This java file must not contain an actual class definition (which would be illegal anyways, because package-info is not a legal identifier).



Built-in Annotations
Java 1.5 comes packaged with seven pre-built annotations. I will describe these built-in annotations in this section, borrowing much of the wording directly from the Java 5 documentation.

java.lang.Override


@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override
This annotation is used to indicate that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.

This annotation is useful in avoiding the situation where you think you are overriding a method, but you misspell the method name in the child class. The code in the method you are trying to override in the parent class will be used because the name is misspelled in the child class. This is usually a difficult bug to track down because no compiler or runtime error is thrown. But marking a method with the Override annotation would help you realize this type of problem at compile time rather than through arduous debugging.

java.lang.Deprecated


@Documented
@Retention(value=RUNTIME)
public @interface Deprecated
A program element annotated @Deprecated is one that programmers are discouraged from using, typically because it is dangerous or because a better alternative exists. Using this annotation, compilers warn when a deprecated program element is used or overridden in non-deprecated code.

java.lang.SuppressWarning


@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings
This annotation indicates that the named compiler warnings should be suppressed in the annotated element (and in all program elements contained in the annotated element). Note that the set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements. For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings will be suppressed in the method.

java.lang.annotation.Documented


@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Documented
Annotations with a type declaration are to be documented by javadoc and similar tools by default. It should be used to annotate the declarations of types whose annotations affect the use of annotated elements by their clients. If a type declaration is annotated with @Documented, its annotations become part of the public API of the annotated elements.

java.lang.annotation.Inherited


@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited
This indicates that an annotation type is automatically inherited. If an inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation.

Note that this meta-annotation type has no effect if the annotated type is used for anything other than a class. Also, this meta-annotation causes annotations to be inherited only from superclasses; annotations on implemented interfaces have no effect.

java.lang.annotation.Retention


@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention
Retention takes a single value of the enumerated type RetentionPolicy, which informs the compiler of its policy for retaining annotations in memory. There are three RetentionPolicy enumerated values:
  • SOURCE—Annotations are to be discarded by the compiler.
  • CLASS—Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at runtime. This is the default behavior.
  • RUNTIME—Annotations are to be recorded in the class file by the compiler and retained by the VM at runtime, so they may be read reflectively.

If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS. By default, the annotation data is not available in the JVM in order to reduce overhead.

java.lang.annotation.Target


@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target
@Target indicates the kinds of program element to which an annotation type is applicable. It takes a single enumerated parameter of type ElementType. The enumerated values are as follows:
  • TYPE (class, interface or enum declaration)
  • FIELD (includes enum constants)
  • METHOD
  • PARAMETER
  • CONSTRUCTOR
  • LOCAL_VARIABLE
  • ANNOTATION_TYPE
  • PACKAGE
If a @Target meta-annotation is not present on an annotation type declaration, the declared type may be used on any program element. If such a meta-annotation is present, the compiler will enforce the specified usage restriction.



Declaring Annotation Types
Now that you've learned a little about the annotations that come packaged with Java 1.5, you can move on to declaring your own annotation types.

Here is a sample annotation type:


public @interface MyAnnotationType {
    int someValue();
    String someOtherValue();
    String yesSomeOtherValue() default "[blank]";

}
As you can see, annotation types are declared similarly to interfaces. In fact they use the interface keyword prepended with an @ sign. Just like an interface, annotations have method declarations, each of which defines a member of the annotation. These methods may not have any parameters. As shown in the example, default values are specified after the parenthesis on a method declaration.

At first, it seems a little odd to specify the members of an annotation using method syntax, because when you declare a Java element and annotate it (e.g. when you annotate a class), you may pass values into the annotation. But you are not the consumer of the annotation at this point; you are merely constructing an instance of the annotation. Think of it as calling a constructor on an implicit Java class that you didn't have to write.

The annotation consumers are the development tools, the compiler, or a runtime library that accesses the annotation data you created when you annotated your Java code. After you've created the annotation, annotation consumers may call the methods on the annotation interface in order to get the annotation values. The return types of the methods represent the type of data that a consumer of the annotation would get back.

There are a few restrictions when defining annotation types.

  • Annotations cannot extend other annotations, except for the java.lang.annotation.Annotation marker interface they inherently extend.
  • Method return types must be: primitive types, String, Class, enum types, annotation types, or arrays of the preceding types.
  • Annotations can't have a throws clause.
  • Self reference is not allowed (e.g. AnnotationA contains a member of type AnnotationA), nor circular reference (e.g. AnnotationA contains a member of type AnnotationB and vice versa).
  • Single member annotations must define only a single method called value in the annotation type. So long as you follow this construct, you can use the condensed single-member syntax when creating an annotation of this type.

    A single member annotation can be defined as follows:
    
    public @interface Copyright {
        String value();
    }
    
You can also create meta-annotations, as we have already seen. A meta-annotation is any annotation that can be used to annotate other annotations. For example, all of the build-in annotations utilize meta-annotations and some of them are meta-annotations themselves.

Here is the declaration for the @ Inherited meta-annotation type:


@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited
The @Inherited annotation uses three other meta-annotations and is a meta-annotation itself. What makes it a meta-annotation? Any annotation whose @Target annotation member includes ANNOTATION_TYPE can be used as a meta-annotation.

Reading Annotations
Now that you know how to declare your own annotation types and annotate Java elements, you need to know how to access the annotation data you specified. Annotation consumers are software that read annotation data and do something useful with it. Annotation consumers fall into three groups:

General tools are programs that can analyze source code and do something useful with it. For example compilers and documentation generators are both considered general tools. General tools do not load annotated classes or annotation interfaces into the virtual machine.

Specific tools are also programs that can analyze source code without loading annotated classes, but they need to load annotation interfaces into the virtual machine. An example of this is a Stub generator.

Introspectors are programs that can query their own annotations (the ones with a RUNTIME retention policy). Introspectors will load both annotated classes and annotation interfaces into the virtual machine.

Listing 1 is an example of how you can access your code during runtime using the reflection API.

As I mentioned previously, I think that most developers will be users of annotations, but few will have to write code that consumes annotations.

If you are a general or specific tools developer, you may want to look into a few APIs that will help you read annotations from source files in order to use them for some type of static preprocessing. The new Doclet API (com.sun.javadoc) has support for reading annotations. It doesn’t currently support all of the features of annotations, but it may suffice as a library for writing your tool. Another thing to keep an eye on is the newly submitted JSR-269 (Pluggable Annotation Processing API), which will provide a generic API that allows developers to read annotation data using general and specific tools.

If you are developing an introspector, you can use the new reflection API to access your annotations, though I would suggest looking into AOP as a means to interface with annotated methods. I think there is a lot of room for exploration here. The combinations of aspects and annotations can yield a very powerful introspection tool.

Javid Jamae consults for Valtech, a global consulting group specializing in delivering advanced technology solutions. Valtech endeavors to help its customers through its global delivery model to create and/or maintain an affordable competitive advantage.

'java core' 카테고리의 다른 글

jar  (0) 2005.04.25
Runtime in jdk5.0  (0) 2005.03.26
Java condition variable  (0) 2005.02.18
Threads from aritma  (0) 2005.02.12
Reference object model from java world  (0) 2005.01.28
Posted by '김용환'
,