직접써야되는데... 게으른 스머프이다보니.. ㅡㅡ;;
네이버에 좋은 글이 있기에 퍼봅니다.

===========================================

우선 인터페이스라고 하면 해당하는 메소드에 대한 선언을 가지고 있죠.

해당 인터페이스를 구현하면 비교의 역할이 있음을 알려주고, 해당 타입으로 캐스팅 정의할 수 있도록 처리를 해줍니다.

즉.. 다음과 같은 형태가 되는거죠.

public class A implements Comparable {
// Return 타입 : 음수(작은경우), 0(같으면), 양수(크면)
public int compareTo(Object o) {
.......;
return int값;
}
}

인터페이스를 상속받았으므로 해당 클래스가 compareTo()메소드를 정의하도록 되어있죠. 따라서 비교는 프로그래머가 정의를 하게 됩니다.

그럼 사용은 어떻게 할까요..
public int insertNode(Comparable key) {
A a = new A();
....; // 처리로직
return a.compareTo(key);
}

위에서 볼 부분은 물론 a.compareTo(key);부분이죠..
a는 Comparable를 구현했으므로 비교가 가능하겠죠.
key 파라미터로는 A클래스가 오면 됩니다. Comparable 인터페이스를 구현했으므로 ClassCaseException이 발생하지는 않겠죠.

만약 B라는 클래스도 위의 A클래스처럼 Comparable 인터페이스를 구현한다면..
public int insertNode(Comparable key) {
B b = new B();
....; // 처리로직
return b.compareTo(key);
}
와 같이 사용해도 아무런 문제는 없겠죠. A클래스와 마찬가지로 B클래스도 Comparable 인터페이스를 상속받았으니까요..

따라서 insertNode()라는 메소드를 서로 다른 클래스에서 Comparable를 구현한 어떤 클래스던지 동일한 메소드명으로 사용이 가능하게 되는거죠.

아래와 같이 A나 B클래스 내부에 정의를 할수도 있습니다.
public class A implements Comparable {
......
public int insertNode(Comparable key) {
....; // 처리로직
return this.compareTo(key);
}
}

public class B implements Comparable {
......
public int insertNode(Comparable key) {
....; // 처리로직
return this.compareTo(key);
}
}

자바 API에는 Serializable이나 Cloneable과 같이 단순히 역할을 정의함으로써 JVM에서 처리하도록 표시만 해주는 Marker Interface가 있는가 하면, Comparable 인터페이스처럼 공통적인 역할을 제시하고 메소드를 필요에 따라 구현하도록 하는 Interface도 있습니다.

위의 인터페이스 용도는 대부분의 자바API가 그런 것처럼 클래스나 인터페이스명에 그대로 나타납니다. 즉 Comparable은 '비교할수 있는..'기능을 정의한 인터페이스입니다.
Posted by 아름프로



developerWorks  > Java technology >
              
developerWorks
Annotations in Tiger, Part 2: Custom annotations
82 KBe-mail it!
Contents:
Defining your own annotation type
Annotating an annotation
Conclusion
Resources
About the author
Rate this article
Related content:
Annotations in Tiger, Part 1: Add metadata to Java code
Taming Tiger
IBM developer kits for the Java platform (downloads)
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
Write your own annotations in Java 5

Level: Introductory

Brett McLaughlin (brett@newInstance.com)
Author/Editor, O'Reilly Media, Inc.
02 Sep  2004

Part 1 of this series introduced annotations, the new metadata facility in J2SE 5.0, and focused on Tiger's basic built-in annotations. A more powerful related feature is support for writing your own annotations. In this article Brett McLauglin shows how to create custom annotations and then how to annotate your annotations to document and customize your code further.


In the first article in this series, I explained what metadata is, why it's valuable, and how to use the basic built-in annotations introduced in J2SE 5.0 (aka Tiger). If you're comfortable with these concepts now, you might already be thinking that the three standard annotations Java 5 offers aren't especially robust. You can do only so much with Deprecated, SuppressWarnings, and Override. Fortunately, Tiger also lets you define your own annotation types. In this article, I'll take you through this relatively simple process with some examples. You'll also find out how to annotate your own annotations and what you gain by doing so. My thanks to O'Reilly Media, Inc., which has graciously allowed me to use the code sample from the annotations chapter of my book on Tiger for this article (see Resources).





Defining your own annotation type
With the addition of a little syntax (and Tiger has added plenty of syntactical constructs), the Java language supports a new type -- the annotation type. An annotation type looks a lot like an ordinary class, but it has some unique properties. Most notably, you can use it with the at sign (@) in your classes to annotate your other Java code. I'll walk you through the process piece by piece.




    

The @interface declaration
Defining a new annotation type is a lot like creating an interface, except that you precede the interface keyword with the @ sign. Listing 1 shows an example of the simplest possible annotation type:




Listing 1. A very simple annotation type



package com.oreilly.tiger.ch06;

/**
* Marker annotation to indicate that a method or class
*   is still in progress.
*/
public @interface InProgress { }


Listing 1 is pretty self-explanatory. If you compile this annotation type and ensure that it's in your classpath, you can then use it on your own source code methods to indicate that a method or class is still in progress, as in Listing 2:



Listing 2. Using your custom annotation type


@com.oreilly.tiger.ch06.InProgress
public void calculateInterest(float amount, float rate) {
  // Need to finish this method later
}


You use the annotation type in Listing 1 exactly the same way you use the built-in annotation types, except that you indicate the custom annotation by both its name and package. Of course, normal Java rules apply, so you can import the annotation type and refer to it as simply @InProgress.




  

Don't miss the rest of this series
Be sure to read, "Part 1" of this series, which introduces annotations in Java 5.0.
  


  
  


Adding a member
The basic usage I've just shown you is far from robust. As you'll remember from Part 1, annotation types can have member variables (see Resources). This is useful, especially when you begin to use annotations as more-sophisticated metadata, not just raw documentation. Code-analysis tools like to have lots of information to crunch, and custom annotations can supply that information.




Data members in annotation types are set up to work using limited information. You don't define a member variable and then provide accessor and mutator methods. Instead, you define a single method, named after the member, that you want to allow for. The data type should be the return value of the method. The concrete example in Listing 3 should make this somewhat confusing requirement more clear:



Listing 3. Adding a member to an annotation type


package com.oreilly.tiger.ch06;

/**
* Annotation type to indicate a task still needs to be
*   completed.
*/
public @interface TODO {
  String value();
}


As odd as Listing 3 might look, it's what you need in annotation types. Listing 3 defines a string named value that the annotation type can accept. You then use the annotation type as in Listing 4:



Listing 4. Using an annotation type with a member value


@com.oreilly.tiger.ch06.InProgress
@TODO("Figure out the amount of interest per month")
public void calculateInterest(float amount, float rate) {
  // Need to finish this method later
}



Again, not much is tricky here. Listing 4 assumes that com.oreilly.tiger.ch06.TODO has been imported, so in the source, you don't prefix the annotation with its package name. Also note that Listing 4 uses the shorthand approach: You feed the value ("Figure out the amount of interest per month") into the annotation without specifying the member-variable name. Listing 4 is equivalent to Listing 5, which doesn't use the shorthand:



Listing 5. "Longhand" version of Listing 4



@com.oreilly.tiger.ch06.InProgress
@TODO(value="Figure out the amount of interest per month")
public void calculateInterest(float amount, float rate) {
  // Need to finish this method later
}


Of course, we're all coders, so who wants to mess with the longhand version? Take note, though -- the shorthand version is available only if the annotation type has a single-member variable named value. If you don't meet this condition, you lose the shorthand feature.



Setting default values
What you've seen so far is a good start, but you have plenty of ways to spruce it up. Probably the next addition you'll think of is to set some default values for the annotation. This is nice when you want users to specify some values, but they need to specify other values only if they differ from the default. Listing 6 illustrates both this concept and its implementation with another custom annotation -- a fuller-featured version of the TODO annotation type from Listing 4:




Listing 6. Annotation type with default values


package com.oreilly.tiger.ch06;

public @interface GroupTODO {

  public enum Severity { CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION };

  Severity severity() default Severity.IMPORTANT;
  String item();
  String assignedTo();
  String dateAssigned();
}


The GroupTODO annotation type in Listing 6 adds several new variables. Note that this annotation type doesn't have a single-member variable, so you gain nothing by naming one of the variables value. Any time you have more than one member variable, you should name them as precisely as possible. You don't get the benefit of the shorthand syntax shown in Listing 5, so you might as well be a little more verbose and create better self-documentation for your annotation type.



Another new feature that Listing 6 demonstrates is that the annotation type defines its own enumeration. (Enumerations -- usually just called enums -- are another new feature of Java 5. This isn't anything remarkable, or even specific to annotation types.) Then, Listing 6 uses the new enumeration as the type for the member variable.



Finally, back to the subject at hand -- default values. Establishing them is pretty trivial. You add the keyword default at the end of the member declaration, and then supply the default value. As you might expect, this must be the same type that you declared for the member variable. Again, this isn't rocket science -- just a little bit of a lexical twist. Listing 7 shows the GroupTODO annotation in action, in a case in which severity is not indicated:



Listing 7. Taking advantage of default values


  @com.oreilly.tiger.ch06.InProgress
  @GroupTODO(
    item="Figure out the amount of interest per month",
    assignedTo="Brett McLaughlin",
    dateAssigned="08/04/2004"
  )
  public  void calculateInterest(float amount, float rate) {
    // Need to finish this method later
  }


Listing 8 shows the same annotation in use, this time with a value supplied for severity:



Listing 8. Overriding default values


  @com.oreilly.tiger.ch06.InProgress
  @GroupTODO(
    severity=GroupTODO.Severity.DOCUMENTATION,
    item="Need to explain how this rather unusual method works",
    assignedTo="Jon Stevens",
    dateAssigned="07/30/2004"
  )
  public  void reallyConfusingMethod(int codePoint) {
    // Really weird code implementation
  }




Annotating an annotation
Before closing the book on annotations (at least in this series), I'll deal briefly with annotating annotations. The set of predefined annotation types you learned about in Part 1 have a predetermined purpose. However, as you move into writing your own annotation types, the purpose of your annotation types isn't always self-evident. In addition to basic documentation, you'll probably write types that are specific to a certain member type, or perhaps a certain set of member types. This requires you to supply some sort of metadata on your annotation type, so that the compiler can enforce the annotation's intended functionality.




Of course, annotations -- the Java language's choice for metadata -- should immediately come to mind as the solution.  You can use four predefined annotation types -- referred to as meta-annotations -- to annotate your annotations. I'll cover each one in turn.



Specifying the target
The most obvious meta-annotation is one that allows you to indicate which program elements can have annotations of the defined type. Unsurprisingly, this meta-annotation is called Target. Before you see how to use Target, though, you need to know about another new class -- actually an enum -- called ElementType. This enum defines the various program elements that an annotation type can target. Listing 9 show the ElementType enum in its entirety:




Listing 9. The ElementType enum


package java.lang.annotation;

public enum ElementType {
  TYPE,     // Class, interface, or enum (but not annotation)
  FIELD,    // Field (including enumerated values)
  METHOD,   // Method (does not include constructors)
  PARAMETER,    // Method parameter
  CONSTRUCTOR,    // Constructor
  LOCAL_VARIABLE, // Local variable or catch clause
  ANNOTATION_TYPE,  // Annotation Types (meta-annotations)
  PACKAGE   // Java package
}


The enumerated values in Listing 9 are pretty obvious, and you can figure out on your own (with help from the comments) how each one applies. When you use the Target meta-annotation, you supply it at least one of these enumerated values and indicate which program elements the annotated annotation can target. Listing 10 shows Target in action:



Listing 10. Using the Target meta-annotation


package com.oreilly.tiger.ch06;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

/**
* Annotation type to indicate a task still needs to be completed
*/
@Target({ElementType.TYPE,
         ElementType.METHOD,
         ElementType.CONSTRUCTOR,
         ElementType.ANNOTATION_TYPE})
public @interface TODO {
  String value();
}


Now the Java compiler will apply TODO only to types, methods, constructors, and other annotation types. This helps you ensure that nobody else takes your annotation type and misapplies it (or, better yet, that you don't misapply it in a fit of fatigue).



Setting retention
The next meta-annotation you want to get under your fingers is Retention. This meta-annotation is related to how the Java compiler treats the annotated annotation type. The compiler has several options:


  • Retain the annotation in the compiled class file of the annotated class, and read it when the class first loads

  • Retain the annotation in the compiled class file, but ignore it at runtime

  • Use the annotation as indicated, but then discard it in the compiled class file





These three options are represented in the java.lang.annotation.RetentionPolicy enum, shown in Listing 11:



Listing 11. The RetentionPolicy enum


package java.lang.annotation;

public enum RetentionPolicy {
  SOURCE,   // Annotation is discarded by the compiler
  CLASS,    // Annotation is stored in the class file, but ignored by the VM
  RUNTIME   // Annotation is stored in the class file and read by the VM
}


As you should expect by now, the Retention meta-annotation type takes as its single argument one of the enumerated values you see in Listing 11. You target this meta-annotation to your annotations, as shown in Listing 12:



Listing 12. Using the Retention meta-annotation


@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
  // annotation type body
}


As you can tell from Listing 12, you can use the shorthand form here, because Retention has a single-member variable. And if you want the retention to be RetentionPolicy.CLASS, you don't have to do a thing, because that's the default behavior.



Adding public documentation
The next meta-annotation is Documented. This is another one that's pretty easy to understand, partly because Documented is a marker annotation. As you should remember from Part 1, marker annotations have no member variables.  Documented indicates that an annotation should appear in the Javadoc for a class. By default, annotations are not included in Javadoc -- a fact worth remembering when you spend a lot of time annotating a class, detailing what's left to do, what it does correctly, and otherwise documenting its behavior.




Listing 13 shows what the Documented meta-annotation looks like in use:



Listing 13. Using the Documented meta-annotation


package com.oreilly.tiger.ch06;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Marker annotation to indicate that a method or class
*   is still in progress.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface InProgress { }


The one "gotcha" with Documented is in the retention policy. Notice that Listing 13 specifies the annotation's retention as RUNTIME.  This is a required aspect of using the Documented annotation type. Javadoc loads its information from class files (not source files), using a virtual machine. The only way to ensure that this VM gets the information for producing Javadoc from these class files is to specify the retention of RetentionPolicy.RUNTIME. As a result, the annotation is kept in the compiled class file and is loaded by the VM; Javadoc then picks it up and adds it to the class's HTML documentation.



Setting up inheritance
The final meta-annotation, Inherited, is probably the most complicated to demonstrate, the least-often used, and the one that creates the most confusion. All that said, let's cheerily run through it.




First, take a use case: Suppose that you mark a class as being in progress, through your own custom InProgress annotation. No problem, right? This will even show up in the Javadoc if you've correctly applied the Documented meta-annotation. Now, suppose you write a new class and extend the in-progress class. Easy enough, right? But remember that the superclass is in progress. If you use the subclass, and even look at its documentation, you get no indication that anything is incomplete. You would expect to see that the InProgress annotation is carried through to subclasses -- that it's inherited -- but it isn't. You must use the Inherited meta-annotation to specify the behavior you want, as shown in Listing 14:



Listing 14. Using the Inherited meta-annotation


package com.oreilly.tiger.ch06;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Marker annotation to indicate that a method or class
*   is still in progress.
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InProgress { }


With the addition of @Inherited, you'll see the InProgress annotation show up on subclasses of annotated classes. Of course, you don't really want this behavior on all your annotation types (that's why the default is not to inherit); for example, the TODO annotation wouldn't (and shouldn't) be propagated. Still, for the case I've shown here, Inherited can be quite helpful.




Conclusion
At this point, you're ready to go back into the Java world and document and annotate everything. Then again, this reminds me a bit of what happened when everyone figured out Javadoc. We all went into the mode of over-documenting everything, before someone realized that Javadoc is best used for clarification of confusing classes or methods. Nobody looks at those easy-to-understand getXXX() and setXXX() methods you worked so hard to Javadoc.




The same trend will probably occur with annotations, albeit to a lesser degree. It's a great idea to use the standard annotation types often, and even heavily. Every Java 5 compiler will support them, and their behavior is well-understood. However, as you get into custom annotations and meta-annotations, it becomes harder to ensure that the types you work so hard to create have any meaning outside of your own development context. So be measured. Use annotations when it makes sense to, but don't get ridiculous. However you use it, an annotation facility is nice to have and can really help out in your development process.



      

Resources

  • Don't miss Part 1 of this series, which introduces annotations in Java 5.0.

  • The open source XDoclet code-generation engine enables attribute-oriented programming for the Java language.

  • JSR 175, the specification for incorporating a metadata facility into the Java language, is in proposed final draft status under the Java Community Process.

  • Visit Sun's home base for all things J2SE 5.0..

  • You can download Tiger and try it out for yourself.

  • John Zukowski's series Taming Tiger covers the new features of Java 5.0 in practical tip-based format.

  • Java 1.5 Tiger: A Developer's Notebook (O'Reilly & Associates; 2004), by Brett McLaughlin and David Flanagan, covers almost all of Tiger's newest features -- including annotations -- in a code-centric, developer-friendly format.

  • Find hundreds more Java technology resources on the developerWorks Java technology zone.

  • Visit the Developer Bookstore for a comprehensive listing of technical books, including hundreds of Java-related titles.

  • Interested in test driving IBM products without the typical high-cost entry point or short-term evaluation license? The developerWorks Subscription provides a low-cost, 12-month, single-user license for WebSphere®, DB2®, Lotus®, Rational®, and Tivoli® products -- including the Eclipse-based WebSphere Studio IDE -- to develop, test, evaluate, and demonstrate your applications.


About the author
Author photoBrett McLaughlin has worked in computers since the Logo days (remember the little triangle?). In recent years, he's become one of the most well-known authors and programmers in the Java and XML communities. He's implemented complex enterprise systems at Nextel Communications, written application servers at Lutris Technologies, and now writes and edits books for O'Reilly Media, Inc.



Posted by 아름프로



한국 developerWorks > 자바 >
developerWorks
Annotations in Tiger, Part 1: 메타데이터를 자바 코드에 추가하기
e-mail it!
목차:
메타데이터의 가치
어노테이션의 기초
Override 어노테이션
Deprecated 어노테이션
SuppressWarnings 어노테이션
결론
참고자료
필자소개
관련자료:
Annotations in Tiger, Part 2: Custom annotations
Taming Tiger
IBM developer kits for the Java platform (downloads)
Subscriptions:
dW newsletters
Java 5의 빌트인 어노테이션을 사용하는 방법

난이도 : 초급

Brett McLaughlin (brett@newInstance.com)
Author/Editor, O'Reilly Media, Inc.
2004년9월 02일

J2SE 5.0 (Tiger)의 새로운 기능인 Annotation은 필요가 많은 메타데이터 기능을 핵심 자바 언어로 가져왔다. 메타테이터가 유용하게 쓰이는 이유를 설명하고 자바의 Annotation 소개한다.


프로그래밍, 특히 자바 프로그래밍의 최신 경향 중 하나는 metadata를 사용한다는 것이다. 메타데이터는 간단히 말해서 데이터에 대한 데이터이다. 메타데이터는 문서화에 사용될 수 있고 코드 의존성을 트래킹하는데 사용되며 심지어 초기 컴파일 시간 체크를 수행 할 때도 사용될 수 있다. XDoclet 같은 (참고자료)메타데이터용 툴들은 이러한 기능을 핵심 자바 언어로 가져왔고 얼마 동안 자바 프로그래밍 관습의 일부가 되었다.



J2SE 5.0 (일명 Tiger)이 나오기 전 까지, 핵심 자바 언어는 javadoc 방법론과 함께 메타데이터 장치에 근접했다. 특별한 태그 세트를 사용하여 코드를 마크업(mark-up)하고 그런 다음 javadoc 명령어를 실행하여 태그를 포맷된 HTML로 변환하여 태그들이 어태치 될 클래스들을 문서화한다. 하지만 Javadoc은 부적당한 메타데이터 툴이다. 문서들을 모으는 것 이상의 다른 목적의 데이터들을 얻을 수 있는 견고하고 표준화된 방법이 없기 때문이다. HTML 코드가 종종 Javadoc 아웃풋과 섞인다는 사실이 이를 더욱 증명하고 있다.



Tiger는 어노테이션이라는 새로운 기능을 통해 보다 다양한 메타데이터 장치를 핵심 자바 언어에 추가했다. 어노테이션은 코드에 추가할 수 있고, 패키지 선언, 유형 선언, 생성자, 메소드, 필드, 매개변수, 변수에 적용할 수 있는 변경자(modifier)이다. Tiger에는 빌트인 어노테이션이 추가되었고 직접 작성할 수 있는 커스텀 어노테이션도 지원한다. 이 글에서는 메타테이터의 효용을 설명하고 Tiger의 빌트인 어노테이션을 소개하겠다. Part 2에서는 커스텀 어노테이션에 대해 자세히 알아 볼 것이다. O'Reilly Media, Inc.에 특별히 감사한다. 이들의 도움으로 내 저서의 어노테이션 챕터에서 코드 샘플을 인용할 수 있었다.(참고자료)



메타데이터의 가치
일반적으로 메타데이터의 효용은 세 가지로 나눌 수 있다. 문서화, 컴파일러 체크, 코드 분석. 코드 레벨의 문서화는 가장 자주 인용되는 사용법이다. 메타데이터는 메소드가 다른 메소드에 의존하고 있다는 것을 가르키는 유용한 방법을 제공한다. 또한 그들이 불완전한지, 특정 클래스가 또 다른 클래스를 레퍼런싱 하는지 등을 가르킨다. 이는 정말로 유용하지만 문서화는 메타데이터를 자바에 추가하는 것과 가장 관련이 적은 항목이다. 코드의 문서화에 있어서는 Javadoc이 사용이 쉽고 강력한 방식을 제공하고 있기 때문이다. 이미 사용하고 있는 것이 있고 작동도 잘 되고 있는데 문서를 굳이 만들 필요는 없지 않는가?






Part 2를 놓치지 마세요!
커스텀 어노테이션을 설명하는 "Part 2"도 잊지 말고 읽어주시기 바랍니다.






컴파일러 체크
보다 중요한 메타데이터의 장점은 컴파일러가 메타데이터를 사용하여 몇 가지 기본적인 컴파일 시간 체크를 수행할 수 있는 기능이라고 할 수 있다. 예를 들어, 이 글의 The Override 어노테이션섹션에서 Tiger 는 메소드가 또 다른 메소드를 수퍼클래스에서 겹쳐 쓰게끔 지정하는 어노테이션을 도입한다. 자바 컴파일러는 메타데이터에서 가르키는 작동이 실제로 코드 레벨에서 발생한다는 것을 확인할 수 있다. 이러한 유형의 버그를 추적해 본 적이 없다면 어리석은 일 같지만 대부분의 자바 프로그래밍 베테랑들은 코드가 왜 작동하지 않는지를 밝혀내기 위해서 밤을 지새우기도 하는 법이다. 메소드가 잘못된 매개변수를 갖고 있고 사실 수퍼클래스에서 메소드를 겹쳐 쓰지 않는다는 것을 발견했을 때의 씁쓸함이란... 메타데이터를 소비하는 툴을 사용하면 이러한 유형의 에러를 쉽게 발견할 수 있다. 많은 밤을 뜬눈으로 지새우지 않아도 된다.






JSR 175
JSR 175(자바 프로그래밍 언어를 위한 메타테이터 장치) 메타데이터를 핵심 자바 언어로 결합하는 공식 스팩을 제공한다.(참고자료) JSR에 따르면 어노테이션은 "프로그램의 문법에 직접적인 영향을 주지 않는다. 하지만 개발과 전개 툴은 이러한 어노테이션을 읽고 특정 방식으로 처리하면서 부가적인 자바 프로그래밍 언어 소스 파일, XML 문서 등을 만들어내서 어노테이션을 포함하고 있는 프로그램과 결합하여 사용될 수 있게 한다."




코드 분석
아마도 좋은 어노테이션 또는 메타데이터 툴의 최고의 기능은 여분의 데이터를 사용하여 코드를 분석하는 것이다. 간단한 경우, 코드 목록을 구현하고 필요한 인풋 유형을 제공하고 리턴 유형을 지시한다. 하지만 자바 리플렉션도 같은 기능을 제공한다고 생각할 수도 있다; 결국 이 모든 정보에 대한 코드를 검사할 수 있다. 표면적으로 볼 때 그럴 듯 하지만 실제로 그렇지 않다. 많은 경우 메소드는 인풋으로서 받아들이거나 아웃풋으로 리턴한다. 이는 메소드가 원하는 것이 아니다. 예를 들어, 매개변수 유형이 Object이지만 메소드는 Integer를 사용해서만 작동한다. 이는 메소드가 겹쳐쓰기된 곳에서 쉽게 발생할 수 있다. 그리고 수퍼클래스가 메소드를 일반 매개변수로 선언하던가 많은 직렬화가 진행되는 시스템에서도 쉽게 발생한다. 두 경우 모두 메타데이터는 코드 분석 툴을 지정할 수 있다. 매개변수 유형이 Object이더라도 정말로 원하는 것은 Integer라는 것을 나타낼 수 있다. 이러한 종류의 분석은 상당히 유용하며 그 가치는 상당하다.




보다 복잡한 경우 코드 분석 툴은 모든 종류의 추가 태스크들을 수행할 수 있다. 그 예 중 하나가 Enterprise JavaBean (EJB) 컴포넌트이다. 심지어 간단한 EJB 시스템으로의 의존성과 복잡함은 상당하다. 로컬 인터페이스와 로컬 홈 인터페이스의 가능성과 함께 홈 인터페이스와 원격 인터페이스를 얻는다. 이 모든 클래스들을 연동시키는 것은 진정한 고통이다. 하지만 메타데이터는 이 문제에 대한 솔루션을 제공한다. 좋은 툴은(예를 들어, XDoclet)은 이 모든 의존성을 관리하면서 "코드-레벨" 연결이 없지만 "로컬-레벨" 관계를 가진 클래스들이 연동될 수 있도록 한다. 이것이 바로 메타테이터의 진정한 가치이다.



어노테이션의 기초
메타데이터가 어디에 좋은 지를 이해했으니 Tiger 의 어노테이션을 소개하겠다. Tiger는 "at" 표시(@)를 취한다. 그 뒤에는 어노테이션 이름이 붙는다. 그런 다음 데이터가 필요할 때 어노테이션에 데이터를 제공한다. (name=value)종류의 표기법을 사용할 때 마다 어노테이션을 만든다. 코드 한 조각은 10, 50 또는 그 이상의 어노테이션을 가진다. 하지만 많은 어노테이션은 같은 어노테이션 유형을 사용한다. 이 유형은 실제 구조체이고 어노테이션 자체는 이 유형의 특정 사용법이다. (사이드 바 참조 어노테이션 또는 어노테이션 유형?)






어노테이션 또는 어노테이션 유형?
어노테이션과 어노테이션 유형이 무엇인지 혼돈스러운가? 가장 쉽게 이해하려면 이미 익숙한 자바 언어 개념의 관점에서 생각해야 한다. 단일 클래스 (예를 들어, Person)를 정의할 수 있고 단 한 버전의 클래스를 JVM에 가질 수 있다. (단, 중첩 클래스 경로를 수행하지 않는 한) 하지만 주어진 시간동안 사용할 때, 이 클래스의 10개 또는 20개의 인스턴스를 갖게 된다. 여전히 단 하나의 Person 클래스만 존재하지만 다양한 방식으로 여러 번 사용된다. 어노테이션 유형과 어노테이션의 경우도 이와 같다. 어노테이션 유형은 클래스와 유사하고 어노테이션은 이 클래스의 인스턴스와 비슷하다.





어노테이션은 세 가지 기본 범주로 나뉜다:




  • Marker 어노테이션은 변수가 없다. 이 어노테이션은 이름으로 구분되며 추가 데이터 없이 나타난다. 예를 들어, @MarkerAnnotation은 marker 어노테이션이다. 데이터가 없으며 단지 어노테이션 이름만 있을 뿐이다.




  • Single-value 어노테이션은 marker와 비슷하지만 데이터를 제공한다. 싱글 비트 데이트를 제공하기 때문에 간단한 신택스를 사용할 수 있다. (단, 어노테이션 유형이 이 문법을 수용해야 함): @SingleValueAnnotation("my data")이는 @표시만 제외하고는 일반적인 자바 메소드 호출과 비슷하다.




  • Full 어노테이션은 다중 데이터 멤버를 갖고 있다. 결과적으로 전체 신택스를 사용해야 한다. (그리고 어노테이션은 일반 자바 메소드와 더 이상 비슷하지 않다): @FullAnnotation(var1="data value 1", var2="data value 2", var3="data value 3")



디폴트 신택스를 통해 어노테이션에 값을 제공하는 것 외에도 한 개 이상의 값을 전달해야 할 때 name-value쌍을 사용할 수 있다. 또한 어노테이션 변수에 값 어레이를 제공할 수 있다. 이때 중괄호({})를 사용한다. Listing 1은 어노테이션에서의 값의 어레이 예제이다.



Listing 1. 어노테이션에서 어레이 값 사용하기



@TODOItems({ // Curly braces indicate an array of values is being supplied
@TODO(
severity=TODO.CRITICAL,
item="Add functionality to calculate the mean of the student's grades",
assignedTo="Brett McLaughlin"
),
@TODO(
severity=TODO.IMPOTANT,
item="Print usage message to screen if no command-line flags specified",
assignedTo="Brett McLaughlin"
),
@TODO(
severity=TODO.LOW,
item="Roll a new website page with this class's new features",
assignedTo="Jason Hunter"
)
})


Listing 1의 예제는 보기보다 간단하다. TODOItems 어노테이션 유형은 값을 취하는 하나의 변수를 갖고 있다. 여기에서 제공되는 값은 매우 복잡하다. 하지만 TODOItems를 사용하면 single-value 어노테이션 스타일과 실제로 맞다. Single value가 어레이라는 것을 제외하면 말이다. 이 어레이는 세 개의 TODO 어노테이션을 포함하고 있는데 각각 값이 증폭된다. 콤마는 각 어노테이션에서 값을 분리하고 하나의 어레이에서의 값도 콤마로 분리된다.



TODOItemsTODO는 커스텀 어노테이션이다. 커스텀 어노테이션은 Part 2의 주제이다. 여러분에게 복잡한 어노테이션을 보여주고 싶었다. Listing 1은 어떤 어노테이션 보다 복잡하지만 그렇게 심하지는 않다. 자바의 표준 어노테이션 유형을 살펴본다면 그렇게 복잡한 것도 드물다. 다음 섹션에서는 Tiger의 기본 어노테이션 유형이 사용하기 쉽다는 것을 알게될 것이다.



Override 어노테이션
Tiger의 첫 번째 빌트인 어노테이션 유형은 Override이다. Override는 메소드에 대해서만 사용되어야 한다. (클래스, 패키지 선언, 기타 구조체는 안된다.) 주석이 첨가된 메소드는 수퍼클래스에서 메소드를 오버라이드한다는 것을 나타낸다. Listing 2는 예제이다.





Listing 2. The Override 어노테이션


package com.oreilly.tiger.ch06;

public class OverrideTester {

public OverrideTester() { }

@Override
public String toString() {
return super.toString() + " [Override Tester Implementation]";
}

@Override
public int hashCode() {
return toString().hashCode();
}
}


Listing 2는 따라가기 쉽다. @Override어노테이션은 두 개의 메소드, toString()hashCode()OverrideTester 클래스의 수퍼클래스 (java.lang.Object)에서 메소드의 버전을 오버라이드 한다는 것을 나타내고 있다. 언뜻 보기에는 사소한 것 같지만 매우 좋은 기능이다. 이들 메소드를 오버라이딩 하지 않고는 클래스를 컴파일 할 수 없다. 어노테이션은 toString()과 썩일 때 적어도 hashCode()와 맞는다는 것을 확인해야 하는 것을 나타낸다.



이 어노테이션 유형은 코딩하기엔 너무 늦었거나 무언가를 잘못 타이핑했을 때 빛을 발한다. (Listing 3)



Listing 3. Override 어노테이션의 오타 찾아내기


package com.oreilly.tiger.ch06;

public class OverrideTester {

public OverrideTester() { }

@Override
public String toString() {
return super.toString() + " [Override Tester Implementation]";
}

@Override
public int hasCode() {
return toString().hashCode();
}
}


Listing 3에서, hashCode()hasCode()로 잘못 표기되었다. 어노테이션은 hasCode()가 메소드를 오버라이드해야 한다는 것을 지시한다. 하지만 컴파일 시, javac는 수퍼클래스(java.lang.Object)가 오버라이드 할 hasCode()라는 메소드가 없다는 것을 알게 된다. 결과적으로 컴파일러는 에러를 표시한다. (그림 1)





그림 1. Override 어노테이션에서의 컴파일러 경고





빠진 기능
Deprecated로 에러 유형 메시지를 single-value 어노테이션 유형으로 포함시킬 수 있도록 한다면 좋을 것이다. 컴파일러는 사용자가 deprecated 메소드를 사용할 때 메시지를 프린트할 수 있다. 메시지는 이 메소드를 사용할 때의 결과가 얼마나 심각한지를 나타낼 수 있다. 이 메소드가 정지할 때 대안을 권할 수도 있다. 아마 다음 J2SE 버전에 포함될 것 같다. (Mustang이 임시 이름이다.)





이 간편한 기능으로 오타를 매우 빠르게 잡을 수 있다.



Deprecated 어노테이션
이제 Deprecated표준 어노테이션 유형을 살펴보자. Override와 마찬가지로 Deprecated는 marker 어노테이션이다. Deprecated를 사용하여 더 이상 사용되지 말아야 하는 메소드에 주석을 단다. Override와 다른 점은, Deprecated는 더 이상 사용되지 말아야 하는(depreciated) 메소드와 같은 라인상에 놓여져야 한다. (이유는 나도 모르겠다.)





Listing 4. Deprecated 어노테이션 사용하기



package com.oreilly.tiger.ch06;

public class DeprecatedClass {

@Deprecated public void doSomething() {
// some code
}

public void doSomethingElse() {
// This method presumably does what doSomething() does, but better
}
}



이 클래스를 컴파일 할 때 비정상적인 그 어떤 것도 기대해서는 안된다. 오버라이드 또는 호출이든 Depreciated 메소드를 사용하면 컴파일러는 어노테이션을 처리하고 메소드가 사용되어서는 안된다는 것을 알게 되고 에러 메시지를 만든다. (그림 2)




그림 2. Deprecated 어노테이션의 컴파일러 경고





컴파일러 경고를 켜고 정상적인 depreciation 경고를 원한다는 것을 자바 컴파일러에게 명령한다. 두 플래그 -deprecated또는 -Xlint:deprecated중 하나와 javac명령어를 사용할 수 있다.



SuppressWarnings 어노테이션
마지막 어노테이션 유형은 SuppressWarnings이다. 이것이 어떤 일을 수행하는지 알아내는 것은 쉽다. 하지만 왜 이 어노테이션이 중요한지는 분명하지 않다. 이는 실제로 Tiger의 새로운 기능의 부작용이다. 예를 들어, generics를 생각해보자. generics는 모든 유형의 새로운 type-safe 작동을 만든다. 특히 자바 컬렉션의 경우 더욱 그렇다. 하지만 generics 때문에 컴파일러는 컬렉션이 type-safety 없이 사용될 때 경고를 던진다. Tiger를 겨냥한 코드에는 유용하지만 Java 1.4.x의 경우엔 코드 작성이 고통 그 자체이다. 전혀 신경 쓰지 않은 것에 대해 경고를 받아야 한다. 컴파일러를 어떻게 하면 없앨 수 있을까?





SupressWarnings는 구원자다. OverrideDeprecated와는 다르게 SupressWarnings는 변수를 갖고 있다. 따라서 이를 작동하게 하려면 싱글-어노테이션 유형을 사용한다. 값 어레이로서 변수를 제공할 수 있다. 각각 삭제할(Suppress) 특정 유형의 경고를 나타낸다. Listing 5의 예제를 보자. Tiger에서 에러를 만드는 코드이다.



Listing 5. type-safe가 아닌 Tiger 코드


public void nonGenericsMethod() {
List wordList = new ArrayList(); // no typing information on the List

wordList.add("foo"); // causes error on list addition
}



그림 3은 Listing 5에서 코드 컴파일을 한 결과이다.




그림 3. non-typed 코드에서 컴파일러 경고





Listing 6은 SuppressWarnings 어노테이션을 사용하여 번거로운 경고를 제거한다.



Listing 6. 경고 제거하기


@SuppressWarnings(value={"unchecked"})
public void nonGenericsMethod() {
List wordList = new ArrayList(); // no typing information on the List

wordList.add("foo"); // causes error on list addition
}


간단하지 않은가? 경고 유형을 배치하고(그림 3의 "unchecked") SuppressWarnings에 전달하면 된다.



SuppressWarnings의 변수 값이 어레이를 취한다는 사실은 같은 어노테이션으로 다중의 경고를 삭제할 수 있음을 의미한다. 예를 들어, @SuppressWarnings(value={"unchecked", "fallthrough"})는 두 개의 값 어레이를 취한다. 이 장치는 매우 유연한 방식을 제공하여 장황하지 않게 에러를 핸들 할 수 있다.




결론
이 글에서 본 문법이 다소 생소하더라도 어노테이션은 이해하기도 쉽고 사용도 쉽다는 것을 알아야 한다. Tiger 에서 제공하는 표준 어노테이션 유형이 어설프고 개선의 여지가 많다. 메타데이터는 점점 유용해지고 있고 자신의 애플리케이션에 맞는 어노테이션 유형을 사용할 수 있을 것이다. Part 2에서는 커스텀 어노테이션 유형을 작성하는 방법을 자세히 다루겠다. 자바 클래스를 만들고 이를 어노테이션 유형으로서 정의하는 방법, 컴파일러가 어노테이션 유형을 인식하게 하는 방법, 코드에 주석을 달 때 이를 사용하는 방법 등을 설명하겠다.





참고자료



필자소개
Author photoBrett McLaughlin은 현재 자바 및 관련 기술을 이용하여 애플리케이션 기반구조 구현을 전문적으로 수행하고 있다. Brett은 Java Apache 프로젝트인 Turbine의 공동 창립자이다.





 

한국 developerWorks > 자바 >
  
 



Posted by 아름프로
번역상에 이상이 있는 부분 알려주세요..
원본은 아래에 링크 했습니다.
===========================================

많은 API들은 많은 boilerplate code(원본에서 변경없이 재사용되어지는 코드)이 필요로 합니다.
예로 JAX-RPC로 웹서비스를 작성하기 위해서는 당신은 인터페이스와 구현체 한쌍을 제공해야만 합니다.
만약 프로그램이 원격에서 접근가능한  메소드를 나타내는 주석(Annotation : 추후 주석으로 해석)들로
장식되어져("decorated")  있다면 툴에 의해서 자동적으로 처리될 수 있습니다.

다른 API들은 프로그램과 동시에 유지되기 위한 "side files"을 필요로 합니다.
예로 JavaBeans는 bean과 동시에 유지되기 위한 BeanInfo 클래스가 필요로 합니다, 그리고
Enterpise JavaBeans(EJB)는 deployment descriptor를 필요로 합니다.
이러한 side files내에 정보가 프로그램 자체의 주석으로써 유지되어지면
더욱 쓰기 편해지고 실수로인한 에러(error-prone)가 줄어들 것입니다.

자바 플랫폼은 항상 다양한 ad hoc annotation mechanisms(임시 변통의 주석 처리방법)을 가지고 있습니다.
예로 transient 제어자(modifier)는 필드가 serialization subsystem에 의해 무시되어지는 것을
나타내는 ad hoc annotation 입니다. 그리고
@deprecated 태그는 메소드가 더이상 사용해서는 안됨을 나타내는 ad hoc annotation 입니다.
현재 릴리즈5.0은 metadata로 알려진 독자적으로 주석타입을 사용하고 정의 할 수 있는
범용적 주석(general purpose annotation) 기능을 가지고 있습니다.
이 기능은 주석타입을 선언하기 위한 구문, 주석처리 선언(annotating declarations)을 위한 구문,
주석을 읽기 위한 API들, 주석을 위한 클래스 파일 표현(a class file representation for annotations),
그리고 주석 처리 툴로 구성됩니다.

주석은 프로그램 시멘틱상에 직접적으로 영향을 주지 않습니다.
그러나 프로그램들이 툴과 라이브러리에 의해서 다뤄지는 방법으로 영향을 미치기 때문에
작동중인 프로그램의 시맨틱에 차례로 영향을 미칠 수 있습니다.
주석은 소스파일, 클래스 파일, 또는 실행시에 리플렉션으로 읽어낼 수 있습니다.

통상의 어플리케이션 프로그래머는 주석타입을 정의할 필요는 없습니다만, 정의하는 것은 그렇게 어려운 것은 아닙니다.
주석 타입 선언은 표준 인터페이스 선언하는거와 유사합니다.
at-sign(@)는 interface 키워드를 선행합니다.(위치적으로 interface키워드 앞에 놓입니다.)
각 메소드선언은 주석타입의 element를 선언합니다.
메소드선언은 parameters 또는 throws 절을 가져서는 안됩니다.
리턴타입은 primitives, String, Class, enums, annotations, 그리고 앞선타입의 배열들에 한정됩니다.
메소드는 기본값(default values)를 가질 수 있습니다.

주석타입 선언(annotation type declaration)의 예제>

        /**
         * Describes the Request-For-Enhancement(RFE) that led
         * to the presence of the annotated API element.
         */
        public @interface RequestForEnhancement {
            int    id();
            String synopsis();
            String engineer() default "[unassigned]";
            String date();    default "[unimplemented]";
        }

주석타입이 선언되면, 선언을 주석처리할 수 있습니다. 주석은 특별한 종류의 제어자(Modifier)이며,
다른 제어자(public, static, or final과 같은)가 사용되어질 수 있는 곳이면 어디서든 사용가능합니다.
단, 규칙(약정)에 의해 주석은 다른 제어자의 앞에 놓인다.
주석은 주석타입에 따른 at-sign(@)와 element-value 쌍으로 둘러쌓인 리스트로 구성된다.
값들은 컴파일타임 상수(compile-time constants)이여야만 한다.
다음은 주석타입에 해당하는 주석을 가지고 메소드선언한 예입니다.

        @RequestForEnhancement(
            id       = 2868724,
            synopsis = "Enable time-travel",
            engineer = "Mr. Peabody",
            date     = "4/1/3007"
        )
        public static void travelThroughTime(Date destination) { ... }

elements를 가지고 있지 않는 주석타입은 "marker" 주석타입이라 불립니다.

예)
        /**
         * Indicates that the specification of the annotated API element
         * is preliminary and subject to change.
         */
        public @interface Preliminary { }

다음에 보여지는 것처럼 marker 주석내에 괄호를 생략할 수 있습니다.

        @Preliminary public class TimeTravel { ... }

단일요소(single element)를 가지는 주석의 경우, 다음에서 보는것 처럼 element는 value 라고 이름지어집니다.

        /**
         * Associates a copyright notice with the annotated API element.
         */
        public @interface Copyright {
            String value();
        }
        
다음에서 보는 것 처럼, element명이 value인 single-element 주석에서는 element명과 등호(=)는 생략할 수 있습니다.

        @Copyright("2002 Yoyodyne Propulsion Systems")
        public class OscillationOverthruster { ... }

이 모든 것을 함게 묶기 위해 우리는 간단한 주석기반 테스트 프레임워크를 만들 것입니다.
첫번째 메소드가 테스트 메소드이고, 테스팅툴에서 실행가능해야하는 것을 나타내는 marker 주석타입이 필요로 합니다.

        import java.lang.annotation.*;
        
        /**
         * Indicates that the annotated method is a test method.
         * This annotation should be used only on parameterless static methods.
         */
        @Retention(RetentionPolicy.RUNTIME)
        @Target(ElementType.METHOD)
        public @interface Test { }

주석타입 선언은 그 자체가 주석이 되어 있는 것을 주의깊게 관찰하십시요.
이러한 주석은 meta-annotation이라고 불려집니다.
첫번째 (@Retention(RetentionPolicy.RUNTIME))는 이와 같은 타입을 가지는 주석은 VM에 의해서 유지되어지고 있기에
런타임에 리플렉션으로 읽어낼 수 있슴을 나타냅니다.
두번째 (@Target(ElementType.METHOD))는 이 주석타입은
단지 메소드선언만을 주석하기 위해서 사용되어지는 것을 나타냅니다.

다음은 일부 메소드가 상위인터페이스와 주석되어지는 예제 프로그램입니다.

        public class Foo {
            @Test public static void m1() { }
            public static void m2() { }
            @Test public static void m3() {
                throw new RuntimeException("Boom");
            }
            public static void m4() { }
            @Test public static void m5() { }
            public static void m6() { }
            @Test public static void m7() {
                throw new RuntimeException("Crash");
            }
            public static void m8() { }
        }

다음은 테스팅 툴입니다.

        import java.lang.reflect.*;

        public class RunTests {
           public static void main(String[] args) throws Exception {
              int passed = 0, failed = 0;
              for (Method m : Class.forName(args[0]).getMethods()) {
                 if (m.isAnnotationPresent(Test.class)) {
                    try {
                       m.invoke(null);
                       passed++;
                    } catch (Throwable ex) {
                       System.out.printf("Test %s failed: %s %n", m, ex.getCause());
                       failed++;
                    }
                 }
              }
              System.out.printf("Passed: %d, Failed %d%n", passed, failed);
           }
        }

툴은 커맨드라인 인수로 클래스명을 이용하고 Test 주석타입(앞서정의 된)으로 주석된
각 메소드를 호출하기 위해 시도하는 지정된 클래스의 모든 메소드 반복처리 합니다.
하나의 메소드가 Test 주석을 가지고 있는지 깨닫기 위한 리플렉티브한 조회는 녹색으로
강조 표시하고 있습니다. 만약 테스트 메소드 주석이 예외사항을 던진다면, 테스트는 실패된
것으로 간주되어 실패 레포트가 출력됩니다.
마지막으로 요점은 처리(성공)되고 실패되어진 테스트의 수가 프린되어집니다.
다음은 Foo 프로그램에 대해서 테스팅 툴을 실행하면 어떤결과가 나오는지 보여줍니다.

        $ java RunTests Foo
        Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
        Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
        Passed: 2, Failed 2

이 테스팅 툴은 알기 쉽게 간단한 것이지만, 주석의 기능(힘)을 설명하고 있고,
그 한계를 극복하기 위해 쉽게 확장할 수 있습니다.
Posted by 아름프로
크게 네부분에서의 성능 향상이 있었습니다.
이중에서 일반 개발자 관점에서의 주목되는 부분은 StringBuffer 클래스의 등장과 어플리케이션 개발 차원에서의 2D쪽과 Image I/O 향상이네요.


Enhancements in JDK 5.0



The following are some of the enhancements made for improved
program execution speed in JDK 5.0.

  • Garbage collection ergonomics - Provides for the automatic
    detection and choice of the client or server runtime compiler,
    which enhances performance on server-class machines.
    See "Server-Class Machine Detection" and "Garbage Collection
    Ergonomics" at Java
    Virtual Machines
    for more information.



  • StringBuilder class - The addition of a new class
    StringBuilder
    that works essentially as an unsynchronized StringBuffer for performance
    enhancement. You should replace all StringBuffer uses with StringBuilder
    unless you need the synchronization (which you almost certainly don't).
    StringBuilder is almost always faster than StringBuffer.



  • Java 2DTM technology -
    These Java 2D performance enhancements have spin-off performance
    benefits in other areas of functionality such as Swing/JFC.
    Examples include improved acceleration for BufferedImage objects,
    support for hardware-accelerated rendering using OpenGL,
    and improved text-rendering performance.
    See New Java 2D Features
    for more information.



  • Image I/O - Performance and memory usage improvements have been
    made when reading and writing JPEG images. See "Improved Performance" at
    Image I/O Features.



Posted by 아름프로
Image I/O Support for BMP and WBMP Formats

BMP와 WBMP 포멧의 읽기 쓰기가 가능해졌습니다.

javax.imageio 패키지를 통해서 JPEG, PNG, BMP, WBMP의 읽기 쓰기가 가능해졌고,
GIF이미지는 읽기기능이 가능해졌습니다.

이 변경에 관련하는 버그 리포트: 4339462 및 4339384


성능 향상 부분

Image I/O API 에 영양을 미치지 않으면서, JPEG 이미지의 읽기, 쓰기 상의 성능과 메모리 향상이 되었습니다.

이 변경에 관련하는 버그 리포트: 4827358 ,4867874 , 및 4868479

Posted by 아름프로
1.4에서 추가된 java.nio 패키지에서의 Charset 지원현황입니다.

기본 인코딩 세트 (lib/rt.jar 에 포함되어 있다)



summary="Basic encoding set">















































java.nio API 용의 정 준명


java.io 및 java.lang API 용의 정 준명


설명


ISO-8859-1


ISO8859_1


ISO 8859-1, 라틴 알파벳 No. 1


ISO-8859-2


ISO8859_2


라틴 알파벳 No. 2


ISO-8859-4


ISO8859_4


라틴 알파벳 No. 4


ISO-8859-5


ISO8859_5


라틴/키릴 문자 알파벳


ISO-8859-7


ISO8859_7


라틴/그리스 문자 알파벳


ISO-8859-9


ISO8859_9


라틴 알파벳 No. 5


ISO-8859-13


ISO8859_13


라틴 알파벳 No. 7


ISO-8859-15


ISO8859_5


라틴 알파벳 No. 9


KOI8-R


KOI8_R


KOI8-R, 러시아어


US-ASCII


ASCII


American Standard Code for Information Interchange


UTF-8


UTF8


8 비트 UCS Transformation Format


UTF-16


UTF-16


16 비트 UCS Transformation Format, 옵션의 바이트순서 마크에 의해 식별되는 바이트순서


UTF-16BE


UnicodeBigUnmarked


16 비트 Unicode Transformation Format, 빅 endian 바이트순서


UTF-16LE


UnicodeLittleUnmarked


16 비트 Unicode Transformation Format, little endian 바이트순서


windows-1250


Cp1250


Windows 동구


windows-1251


Cp1251


Windows 키릴 문자


windows-1252


Cp1252


Windows 라틴 문자-1


windows-1253


Cp1253


Windows 그리스 문자


windows-1254


Cp1254


Windows 터키어


windows-1257


Cp1257


Windows 발트제어


이용할 수 없다


UnicodeBig


16 비트 Unicode Transformation Format, 빅 endian 바이트순서, 바이트순서 마크 첨부


이용할 수 없다


UnicodeLittle


16 비트 Unicode Transformation Format, little endian 바이트순서, 바이트순서 마크 첨부

 



확장 인코딩 세트 (lib/charsets.jar 에 포함되어 있다)



summary="extended encoding set">





























































































































































































































































java.nio API 용의 정 준명


java.io 및 java.lang API 용의 정 준명


설명


Big5


Big5


Big5, 중국어 (번체자)


Big5-HKSCS


Big5_HKSCS


Big5 (홍콩의 확장 첨부), 중국어 (번체자, 2001 개정을 짜넣어)


EUC-JP


EUC_JP


JISX 0201, 0208, 0212, EUC 인코딩, 일본어


EUC-KR


EUC_KR


KS C 5601, EUC 인코딩, 한국어


GB18030


GB18030


중국어 (중공에서 정식으로 쓰는 약자체?), 중화 인민 공화국 표준


GB2312


EUC_CN


GB2312, EUC 인코딩, 중국어 (중공에서 정식으로 쓰는 약자체?)


GBK


GBK


GBK, 중국어 (중공에서 정식으로 쓰는 약자체?)


IBM-Thai


Cp838


IBM 타이 확장 SBCS


IBM00858


Cp858


Cp850 의 확장으로 유로 문자를 포함한다


IBM01140


Cp1140


Cp037 의 확장으로 유로 문자를 포함한다


IBM01141


Cp1141


Cp273 의 확장으로 유로 문자를 포함한다


IBM01142


Cp1142


Cp277 의 확장으로 유로 문자를 포함한다


IBM01143


Cp1143


Cp278 의 확장으로 유로 문자를 포함한다


IBM01144


Cp1144


Cp280 의 확장으로 유로 문자를 포함한다


IBM01145


Cp1145


Cp284 의 확장으로 유로 문자를 포함한다


IBM01146


Cp1146


Cp285 의 확장으로 유로 문자를 포함한다


IBM01147


Cp1147


Cp297 의 확장으로 유로 문자를 포함한다


IBM01148


Cp1148


Cp500 의 확장으로 유로 문자를 포함한다


IBM01149


Cp1149


Cp871 의 확장으로 유로 문자를 포함한다


IBM037


Cp037


미국, 캐나다 (2 개국어, 프랑스어), 네델란드, 포르투갈, 브라질, 오스트레일리아


IBM1026


Cp1026


IBM 라틴 문자-5, 터키


IBM1047


Cp1047


라틴 문자-1 (EBCDIC 호스트용)


IBM273


Cp273


IBM 오스트리아, 독일


IBM277


Cp277


IBM 덴마크, 노르웨이


IBM278


Cp278


IBM 핀란드, 스웨덴


IBM280


Cp280


IBM 이탈리아


IBM284


Cp284


IBM 카타로니아어/스페인, 스페인어권라틴 아메리카


IBM285


Cp285


IBM 영국, 아일랜드


IBM297


Cp297


IBM 프랑스


IBM420


Cp420


IBM 아라비아어


IBM424


Cp424


IBM 헤브라이어


IBM437


Cp437


MS-DOS 미국, 오스트레일리아, 뉴질랜드, 남아프리카


IBM500


Cp500


EBCDIC 500V1


IBM775


Cp775


PC 발트제어


IBM850


Cp850


MS-DOS 라틴 문자-1


IBM852


Cp852


MS-DOS 라틴 문자-2


IBM855


Cp855


IBM 키릴 문자


IBM857


Cp857


IBM 터키어


IBM860


Cp860


MS-DOS 포르투갈어


IBM861


Cp861


MS-DOS 아이슬랜드어


IBM862


Cp862


PC 헤브라이어


IBM863


Cp863


MS-DOS 캐나다계 프랑스어


IBM864


Cp864


PC 아라비아어


IBM865


Cp865


MS-DOS 북유럽


IBM866


Cp866


MS-DOS 러시아어


IBM868


Cp868


MS-DOS 파키스탄


IBM869


Cp869


IBM 근대 희랍어


IBM870


Cp870


IBM 다언어 라틴 문자-2


IBM871


Cp871


IBM 아이슬랜드


IBM918


Cp918


IBM 파키스탄 (우르두어)


ISO-2022-CN


ISO2022CN


ISO 2022 CN 형식의 GB2312 및 CNS11643, 중공에서 정식으로 쓰는 약자체? 및 번체자 중국어 (Unicode 에의 변환만)


ISO-2022-JP


ISO2022JP


ISO 2022 형식의 JIS X 0201, 0208, 일본어


ISO-2022-KR


ISO2022KR


ISO 2022 KR, 한국어


ISO-8859-3


ISO8859_3


라틴 알파벳 No. 3


ISO-8859-6


ISO8859_6


라틴/아라비아어 알파벳


ISO-8859-8


ISO8859_8


라틴/헤브라이어 알파벳


Shift_JIS


SJIS


Shift-JIS, 일본어


TIS-620


TIS620


TIS620, 타이


windows-1255


Cp1255


Windows 헤브라이어


windows-1256


Cp1256


Windows 아라비아어


windows-1258


Cp1258


Windows 베트남어


windows-31j


MS932


Windows 일본어


x-Big5_Solaris


Big5_Solaris


Big5 (Solaris zh_TW.BIG5 로케일용의 7 개의 추가 Hanzi 표의 문자 매핑 첨부)


x-euc-jp-linux


EUC_JP_LINUX


JISX 0201, 0208, EUC 인코딩, 일본어


x-EUC-TW


EUC_TW


CNS11643 (Plane 1-7, 15), EUC 인코딩, 중국어 (번체자)


x-eucJP-Open


EUC_JP_Solaris


JISX 0201, 0208, 0212, EUC 인코딩, 일본어


x-IBM1006


Cp1006


IBM AIX 파키스탄 (우르두어)


x-IBM1025


Cp1025


IBM 다언어 키릴 문자: 불가리아, 보스니아, 헤르체고비나, 마케도니아 ( 구유고슬라비아 마케도니아 공화국)


x-IBM1046


Cp1046


IBM 아라비아어 - Windows


x-IBM1097


Cp1097


IBM 이란 (현대 페르시아어)/페르시아어


x-IBM1098


Cp1098


IBM 이란 (현대 페르시아어)/페르시아어 (PC)


x-IBM1112


Cp1112


IBM 라트비아, 리투아니아


x-IBM1122


Cp1122


IBM 에스토니아


x-IBM1123


Cp1123


IBM 우크라이나


x-IBM1124


Cp1124


IBM AIX 우크라이나


x-IBM1381


Cp1381


IBM OS/2, DOS 중국 (중화 인민 공화국)


x-IBM1383


Cp1383


IBM AIX 중국 (중화 인민 공화국)


x-IBM33722


Cp33722


IBM-eucJP - 일본어 (5050 의 슈퍼 세트)


x-IBM737


Cp737


PC 그리스 문자


x-IBM856


Cp856


IBM 헤브라이어


x-IBM874


Cp874


IBM 타이


x-IBM875


Cp875


IBM 희랍어


x-IBM921


Cp921


IBM 라트비아, 리투아니아 (AIX, DOS)


x-IBM922


Cp922


IBM 에스토니아 (AIX, DOS)


x-IBM930


Cp930


UDC 4370 문자를 포함한 일본어 카타카나 한자, 5026 의 슈퍼 세트


x-IBM933


Cp933


UDC 1880 문자를 포함한 한국어, 5029 의 슈퍼 세트


x-IBM935


Cp935


UDC 1880 문자를 포함한 중공에서 정식으로 쓰는 약자체? 중국어 호스트, 5031 의 슈퍼 세트


x-IBM937


Cp937


UDC 6204 문자를 포함한 번체자 중국어 호스트, 5033 의 슈퍼 세트


x-IBM939


Cp939


UDC 4370 문자를 포함한 일본어 라틴 문자 한자, 5035 의 슈퍼 세트


x-IBM942


Cp942


IBM OS/2 일본어, Cp932 의 슈퍼 세트


x-IBM942C


Cp942C


Cp942 의 확장


x-IBM943


Cp943


IBM OS/2 일본어, Cp932 및 Shift-JIS 의 슈퍼 세트


x-IBM943C


Cp943C


Cp943 의 확장


x-IBM948


Cp948


OS/2 중국어 (대만), 938 의 슈퍼 세트


x-IBM949


Cp949


PC 한국어


x-IBM949C


Cp949C


Cp949 의 확장


x-IBM950


Cp950


PC 중국어 (홍콩, 대만)


x-IBM964


Cp964


AIX 중국어 (대만)


x-IBM970


Cp970


AIX 한국어


x-ISCII91


ISCII91


인도어파 ISCII91 인코딩


x-ISO2022-CN-CNS


ISO2022_CN_CNS


ISO 2022 CN 형식의 CNS11643, 번체자 중국어 (Unicode 로부터의 변환만)


x-ISO2022-CN-GB


ISO2022_CN_GB


ISO 2022 CN 형식의 GB2312, 중공에서 정식으로 쓰는 약자체? 중국어 (Unicode 로부터의 변환만)


x-iso-8859-11


x-iso-8859-11


라틴/타이어 알파벳


x-JISAutoDetect


JISAutoDetect


Shift-JIS, EUC-JP, ISO 2022 JP 의 검출 및 변환 (Unicode 에의 변환만)


x-Johab


x-Johab


한국어, Johab 캐릭터 세트


x-MacArabic


MacArabic


Macintosh 아라비아어


x-MacCentralEurope


MacCentralEurope


Macintosh 라틴 문자-2


x-MacCroatian


MacCroatian


Macintosh 크로아티아어


x-MacCyrillic


MacCyrillic


Macintosh 키릴 문자


x-MacDingbat


MacDingbat


Macintosh Dingbat


x-MacGreek


MacGreek


Macintosh 희랍어


x-MacHebrew


MacHebrew


Macintosh 헤브라이어


x-MacIceland


MacIceland


Macintosh 아이슬랜드어


x-MacRoman


MacRoman


Macintosh Roman


x-MacRomania


MacRomania


Macintosh 루마니아


x-MacSymbol


MacSymbol


Macintosh 심볼


x-MacThai


MacThai


Macintosh 타이


x-MacTurkish


MacTurkish


Macintosh 터키어


x-MacUkraine


MacUkraine


Macintosh 우크라이나


x-MS950-HKSCS


MS950_HKSCS


Windows 번체자 중국어 (홍콩의 확장 첨부)


x-mswin-936


MS936


Windows 중공에서 정식으로 쓰는 약자체? 중국어


x-PCK


PCK


Solaris 판의 Shift_JIS


x-windows-874


MS874


Windows 타이어


x-windows-949


MS949


Windows 한국어


x-windows-950


MS950


Windows 번체자 중국어

Posted by 아름프로
1.5 Tiger에 새롭게 포함된 녀석입니다.

이녀석은
비동기 방식으로 StringBuffer보다 더 빠른 속도를 제공해줍니다.

내용으로는 크게
append 메소드와 insert 메소드가 있는데..

append 는 주어진 문장이나 단어에 제일 끝에 추가가 됩니다.
insert는 주어진 문자이나 단어의 중간의 원하는 곳에 추가를 합니다.

예)

z가 「start」를 포함한 string builder object 라면..
z.append("le")  :  결과는 "startlet"
z.insert(4, "le") : 결과는 "starlet"
가 됩니다.

더 자세한 사항은 API를 참조하세요.
Posted by 아름프로


Internals of Java Class Loading
Internals of Java Class Loading


by Binildas Christudas

01/26/2005






Class loading is one of the most powerful mechanisms provided by
the Java language specification. Even though the internals of class loading
falls under the "advanced topics" heading, all Java programmers should know how
the mechanism works and what can be done with it to suit their
needs. This can save time that would otherwise have been spent debugging
ClassNotFoundException,
ClassCastException, etc.



This article starts from the basics, such as
the difference between code and data, and how they are related to form an instance
or object. Then it looks into the mechanism of loading code into the JVM with the
help of class loaders, and the main type of class loaders available in Java.
The article then looks into the internals of class loaders, where we cover using the
basic algorithm (or probing), followed by class loaders before it loads a class.
The next section of the article uses code examples to demonstrate the necessity
for developers to extend and develop their own class loaders. This is followed
by explanation on writing your own class loaders and how to use them to make a generic
task-execution engine that can be used to load the code supplied by any remote client,
define it in the JVM, and instantiate and then execute it. The article concludes with
references to J2EE-specific components where custom class loading schemas
becomes the norm.



Class and Data





A class represents the code to be executed, whereas data represents the state
associated with that code. State can change; code generally does not.
When we associate a particular
state to a class, we have an instance of that class. So different instances
of the same class can have different state, but all refer to the same code.
In Java, a class will usually have its code contained in a .class
file, though there are exceptions. Nevertheless, in the Java runtime,
each and every class will have its code also available in the form of a first-class Java object, which is an instance of
java.lang.Class.
Whenever we compile any Java file, the compiler will embed a public, static,
final field named class, of the type
java.lang.Class, in the emitted byte code. Since this field is
public, we can access it using dotted notation, like this:



java.lang.Class klass = Myclass.class;




Once a class is loaded into a JVM, the same class (I repeat, the same class)
will not be loaded again. This leads to the question of what is meant by "the same class."
Similar to the condition that an object has a specific state, an identity,
and that an object is always associated with its code (class), a class loaded
into a JVM also has a specific identity, which we'll look at now.




In Java, a class is identified by its fully qualified class name. The fully
qualified class name consists of the package name and the class name. But
a class is uniquely identified in a JVM using its fully qualified class name
along with the instance of the ClassLoader that loaded the class.
Thus, if a class named Cl in the package Pg is loaded by an instance kl1
of the class loader KlassLoader, the class instance of C1, i.e. C1.class is keyed
in the JVM as (Cl, Pg, kl1).
This means that the two class loader instances (Cl, Pg, kl1) and (Cl, Pg, kl2) are not
one and the same, and classes loaded by them are also completely different
and not type-compatible to each other. How many class loader
instances do we have in a JVM? The next section explains this.



Class Loaders




In a JVM, each and every class is loaded by some instance of a
java.lang.ClassLoader. The ClassLoader class is located in
the java.lang package and developers are free to subclass
it to add their own functionality to class loading.




Whenever a new JVM is started by typing java MyMainClass, the "bootstrap class loader" is responsible for loading key Java classes
like java.lang.Object and other runtime code into memory first.
The runtime classes are packaged inside of the JRE\lib\rt.jar file. We cannot
find the details of the bootstrap class loader in the Java documentation, since
this is a native implementation. For the same reason, the behavior of
the bootstrap class loader will also differ across JVMs.




In a related note, we will get null if we try to get the class loader of a core Java runtime class, like this:




log(java.lang.String.class.getClassLoader());



Next comes the Java extension class loader. We can store extension libraries,
those that provide features that go beyond the core Java runtime code,
in the path given by the
java.ext.dirs property. The ExtClassLoader is responsible
for loading all .jar files kept in the java.ext.dirs path.
A developer can add his or her own application .jar files or whatever libraries
he or she might need to add to the classpath to this extension directory
so that they will be loaded by the extension class loader.





The third and most important class loader from the developer perspective
is the AppClassLoader. The application class loader is responsible for
loading all of the classes kept in the path corresponding to the
java.class.path system property.




"Understanding Extension Class Loading" in Sun's Java tutorial explains more on the above three
class loader paths. Listed below are a few other class loaders in the JDK:




  • java.net.URLClassLoader

  • java.security.SecureClassLoader

  • java.rmi.server.RMIClassLoader

  • sun.applet.AppletClassLoader




java.lang.Thread, contains the method public ClassLoader getContextClassLoader(), which returns the context class loader for a particular thread. The context
class loader is provided by the creator of the thread for use by code running in
this thread when loading classes and resources. If it is not set, the default is the
class loader context of the parent thread. The context class loader of the primordial
thread is typically set to the class loader used to load the application.



How Class Loaders Work




All class loaders except the bootstrap class loader have a parent class loader.
Moreover, all class loaders are of the type java.lang.ClassLoader.
The above two statements are different, and very important for the correct
working of any class loaders written by developers. The most important
aspect is to correctly set the parent class loader. The parent class loader
for any class loader is the class loader instance that loaded that class loader.
(Remember, a class loader is itself a class!)



A class is requested out of a class loader using the
loadClass() method. The internal working of this method can be
seen from the source code for java.lang.ClassLoader, given below:




protected synchronized Class<?> loadClass
(String name, boolean resolve)
throws ClassNotFoundException{

// First check if the class is already loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke
// findClass to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}



To set the parent class loader, we have two ways to do so in the ClassLoader constructor:




public class MyClassLoader extends ClassLoader{

public MyClassLoader(){
super(MyClassLoader.class.getClassLoader());
}
}



or




public class MyClassLoader extends ClassLoader{

public MyClassLoader(){
super(getClass().getClassLoader());
}
}



The first method is preferred because calling the method getClass()
from within the constructor should be discouraged, since the object
initialization will be complete only at the exit of the constructor code.
Thus, if the parent class loader is correctly set, whenever a class is
requested out of a ClassLoader instance, if it cannot find the class, it
should ask the parent first. If the parent cannot find it (which again
means that its parent also cannot find the class, and so on), and if the
findBootstrapClass0() method also fails, the
findClass() method is invoked. The default implementation
of findClass() will throw ClassNotFoundException
and developers are expected to implement this method when they subclass
java.lang.ClassLoader to make custom class loaders. The
default implementation of findClass() is shown below.




protected Class<?> findClass(String name)
throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}



Inside of the findClass() method, the class loader needs to fetch
the byte codes from some arbitrary source. The source can be the file system, a network
URL, a database, another application that can spit out byte codes on the fly, or
any similar source that is capable of generating byte code compliant with the
Java byte code specification. You could even use BCEL
(Byte Code Engineering Library), which provides convenient methods to create classes
from scratch at runtime. BCEL is being used successfully in several projects
such as compilers, optimizers, obsfuscators, code generators, and analysis tools.
Once the byte code is retrieved, the method should
call the defineClass() method, and the runtime is very particular
about which ClassLoader instance calls this method. Thus, if two ClassLoader
instances define byte codes from the same or different sources, the defined classes
are different.




The
Java language specification
gives a detailed explanation on the process of
loading,
linking, and the
initialization
of classes and interfaces in the Java Execution Engine.




Figure 1 shows an application with a main class called MyMainClass. As explained
earlier, MyMainClass.class will be loaded by the AppClassLoader. MyMainClass creates
instances of two class loaders, CustomClassLoader1 and CustomClassLoader2, which
are capable of finding the byte codes of a fourth class called Target from some
source (say, from a network path). This means the class definition of the Target
class is not in the application class path or extension class path. In such
a scenario, if MyMainClass asks the custom class loaders to load the Target class, Target
will be loaded and Target.class will be defined independently by both
CustomClassLoader1 and CustomClassLoader2. This has serious implications in Java.
If some static initialization code is put in the Target class, and if we want
this code to be executed one and only once in a JVM, in our current setup the code
will be executed twice in the JVM: once each when the class is loaded separately
by both CustomClassLoaders. If the Target class is instantiated in both the
CustomClassLoaders to have the instances target1 and target2 as shown
in Figure 1, then target1 and target2 are not type-compatible. In other words, the JVM
cannot execute the code:




Target target3 = (Target) target2;



The above code will throw a ClassCastException. This is because the JVM sees these
two as separate, distinct class types, since they are defined by different ClassLoader
instances. The above explanation holds true
even if MyMainClass doesn't use two separate class loader classes like CustomClassLoader1
and CustomClassLoader2, and instead uses two separate instances of a single CustomClassLoader
class. This is demonstrated later in the article with code examples.






Figure 1. Multiple ClassLoaders loading the same Target class in the same JVM




A more
detailed explanation on the process of class loading, defining, and linking is
in Andreas Schaefer's article
"Inside Class Loaders."





















Why Do We Need our Own Class Loaders?




One of the reasons for a developer to write his or her own class loader is to control
the JVM's class loading behavior. A class in Java is identified using
its package name and class name. For classes that implement
java.io.Serializable, the serialVersionUID plays a major role
in versioning the class. This stream-unique identifier is a 64-bit hash of the
class name, interface class names, methods, and fields. Other than these, there
are no other straightforward mechanisms for versioning a class. Technically
speaking, if the above aspects match, the classes are of "same version."




But let us think of a scenario where we need to develop a generic Execution Engine, capable of executing any tasks implementing a particular interface. When the
tasks are submitted to the engine, first the engine needs to load the code for
the task. Suppose different clients submit different tasks (i.e., different code) to
the engine, and by chance, all of these tasks have the same class name and
package name. The question is whether the engine will load the different client
versions of the task differently for different client invocation contexts so that the clients will get the output they expect.
The phenomenon is demonstrated in the sample code download, located in the References section below. Two directories, samepath
and differentversions, contain separate examples to demonstrate the concept.




Figure 2 shows how the examples are arranged in three separate subfolders, called samepath,
differentversions, and differentversionspush:





Figure 2. Example folder structure arrangement




In samepath, we have version.Version classes kept in two subdirectories,
v1 and v2. Both classes have the same name and same package. The only difference
between the two classes is in the following lines:




public void fx(){
log("this = " + this + "; Version.fx(1).");
}



inside of v1, we have Version.fx(1) in the log statement, whereas
in v2, we have Version.fx(2). Put both these slightly different
versions of the classes in the same classpath, and run the Test class:




set CLASSPATH=.;%CURRENT_ROOT%\v1;%CURRENT_ROOT%\v2
%JAVA_HOME%\bin\java Test



This will give the console output shown in Figure 3. We can see that code
corresponding to Version.fx(1) is loaded, since the class loader
found that version of the code first in the classpath.





Figure 3. samepath test with version 1 first in the classpath




Repeat the run, with a slight change in the order of path elements in class path.




set CLASSPATH=.;%CURRENT_ROOT%\v2;%CURRENT_ROOT%\v1
%JAVA_HOME%\bin\java Test



The console output is now changed to that shown in Figure 4. Here, the code
corresponding to Version.fx(2) is loaded, since the class loader
found that version of the code first in the classpath.





Figure 4. samepath test with version 2 first in the classpath




From the above example it is obvious that the
class loader will try to load the class using the path element that is found
first. Also, if we delete the version.Version classes from v1
and v2, make a .jar (myextension.jar) out of version.Version, put it in the path corresponding to java.ext.dirs, and repeat the test, we see
that version.Version is no longer loaded by AppClassLoader
but by the extension class loader, as shown in Figure 5.





Figure 5. AppClassLoader and ExtClassLoader




Going forward with the examples, the folder differentversions contains an RMI execution
engine. Clients can supply any tasks that implement common.TaskIntf
to the execution engine. The subfolders client1 and client2 contain slightly
different versions of the class client.TaskImpl. The difference
between the two classes is in the following lines:




static{
log("client.TaskImpl.class.getClassLoader
(v1) : " + TaskImpl.class.getClassLoader());
}

public void execute(){
log("this = " + this + "; execute(1)");
}



Instead of the getClassLoader(v1) and execute(1) log statements
in execute() inside of client1, client2 has getClassLoader(v2) and
execute(2) log statements. Moreover, in the script to start
the Execution Engine RMI server, we have arbitrarily put the task implementation class
of client2 first in the classpath.




CLASSPATH=%CURRENT_ROOT%\common;%CURRENT_ROOT%\server;
%CURRENT_ROOT%\client2;%CURRENT_ROOT%\client1
%JAVA_HOME%\bin\java server.Server



The screenshots in Figures 6, 7, and 8 show what is happening under the hood.
Here, in the client VMs, separate client.TaskImpl classes are
loaded, instantiated, and sent to the Execution Engine Server VM for execution.
From the server console, it is apparent that client.TaskImpl code
is loaded only once in the server VM. This single "version" of the code is used
to regenerate many client.TaskImpl instances in the server VM,
and execute the task.





Figure 6. Execution Engine Server console




Figure 6 shows the Execution Engine Server console, which is loading and
executing code on behalf of two separate client requests, as shown in Figures 7
and Figure 8. The point to note here is that the code is loaded only once (as
is evident from the log statement inside of the static initialization block), but
the method is executed twice for each client invocation context.





Figure 7. Execution Engine Client 1 console




In Figure 7, the code for the TaskImpl class containing the log statement
client.TaskImpl.class.getClassLoader(v1) is loaded by the client VM,
and supplied to the Execution Engine Server. The client VM in Figure 8 loads
different code for the TaskImpl class containing the log statement
client.TaskImpl.class.getClassLoader(v2), and supplies it to the
Server VM.





Figure 8. Execution Engine Client 2 console




Here, in the client VMs, separate client.TaskImpl classes are
loaded, instantiated, and sent to the Execution Engine Server VM for execution.
A second look at the server console in Figure 6 reveals that the client.TaskImpl code
is loaded only once in the server VM. This single "version" of the code is used
to regenerate the client.TaskImpl instances in the server VM,
and execute the task. Client 1 should be unhappy since instead of his "version"
of the client.TaskImpl(v1), it is some other code that is executed
in the server against Client 1's invocation! How do we tackle such scenarios? The
answer is to implement custom class loaders.





















Custom Class Loaders




The solution to fine-control class loading is to implement custom class loaders.
Any custom class loader should have java.lang.ClassLoader as its
direct or distant super class. Moreover, in the constructor, we need to set the
parent class loader, too. Then, we have to override the findClass()
method. The differentversionspush folder contains a custom class loader called
FileSystemClassLoader. Its structure is shown in Figure 9:





Figure 9. Custom class loader relationship




Below are the main methods implemented in common.FileSystemClassLoader:




public byte[] findClassBytes(String className){

try{
String pathName = currentRoot +
File.separatorChar + className.
replace('.', File.separatorChar)
+ ".class";
FileInputStream inFile = new
FileInputStream(pathName);
byte[] classBytes = new
byte[inFile.available()];
inFile.read(classBytes);
return classBytes;
}
catch (java.io.IOException ioEx){
return null;
}
}

public Class findClass(String name)throws
ClassNotFoundException{

byte[] classBytes = findClassBytes(name);
if (classBytes==null){
throw new ClassNotFoundException();
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}

public Class findClass(String name, byte[]
classBytes)throws ClassNotFoundException{

if (classBytes==null){
throw new ClassNotFoundException(
"(classBytes==null)");
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}

public void execute(String codeName,
byte[] code){

Class klass = null;
try{
klass = findClass(codeName, code);
TaskIntf task = (TaskIntf)
klass.newInstance();
task.execute();
}
catch(Exception exception){
exception.printStackTrace();
}
}



This class is used by the client to convert the client.TaskImpl(v1)
to a byte[]. This byte[] is then send to the RMI
Server Execution Engine. In the server, the same class is used for defining
the class back from the code in the form of byte[]. The client-side
code is shown below:




public class Client{

public static void main (String[] args){

try{
byte[] code = getClassDefinition
("client.TaskImpl");
serverIntf.execute("client.TaskImpl",
code);
}
catch(RemoteException remoteException){
remoteException.printStackTrace();
}
}

private static byte[] getClassDefinition
(String codeName){
String userDir = System.getProperties().
getProperty("BytePath");
FileSystemClassLoader fscl1 = null;

try{
fscl1 = new FileSystemClassLoader
(userDir);
}
catch(FileNotFoundException
fileNotFoundException){
fileNotFoundException.printStackTrace();
}
return fscl1.findClassBytes(codeName);
}
}



Inside of the execution engine, the code received from the client is given
to the custom class loader. The custom class loader will define the class
back from the byte[], instantiate the class, and execute. The
notable point here is that, for each client request, we use separate
instances of the FileSystemClassLoader class to define the client-supplied
client.TaskImpl. Moreover, the client.TaskImpl is
not available in the class path of the server. This means that when we call
findClass() on the FileSystemClassLoader, the
findClass() method calls defineClass() internally, and the
client.TaskImpl class gets defined by that particular instance
of the class loader. So when a new instance of the FileSystemClassLoader
is used, the class is defined from the byte[] all over again. Thus,
for each client invocation, class client.TaskImpl is defined again and
again and we are able to execute "different versions" of the client.TaskImpl
code inside of the same Execution Engine JVM.




public void execute(String codeName, byte[] code)throws RemoteException{

FileSystemClassLoader fileSystemClassLoader = null;

try{
fileSystemClassLoader = new FileSystemClassLoader();
fileSystemClassLoader.execute(codeName, code);
}
catch(Exception exception){
throw new RemoteException(exception.getMessage());
}
}



Examples are in the differentversionspush folder. The server and client
side consoles are shown in Figures 10, 11, and 12:





Figure 10. Custom class loader execution engine




Figure 10 shows the custom class loader Execution Engine VM console. We can see the
client.TaskImpl code is loaded more than once. In fact, for each client
execution context, the class is newly loaded and instantiated.





Figure 11. Custom class loader engine, Client 1




In Figure 11, the code for the TaskImpl class containing the log statement
client.TaskImpl.class.getClassLoader(v1) is loaded by the client VM,
and pushed to the Execution Engine Server VM. The client VM in Figure 12 loads a
different code for the TaskImpl class containing the log statement
client.TaskImpl.class.getClassLoader(v2), and pushes to the
Server VM.





Figure 12. Custom class loader engine, Client 2




This code example shows how we can leverage separate instances of class loaders
to have side-by-side execution of "different versions" of code in the same VM.



Class Loaders In J2EE




The class loaders in some J2EE servers tend to drop and reload classes at different
intervals. This will occur in some implementations and may not on others.
Similarly, a web server may decide to remove a previously loaded servlet instance,
perhaps because it is explicitly asked to do so by the server administrator, or
because the servlet has been idle for a long time. When a request is first made
for a JSP (assuming it hasn't been precompiled), the JSP engine will translate the
JSP into its page implementation class, which takes the form of a standard Java servlet.
Once the page's implementation servlet has been created, it will be compiled into a
class file by the JSP engine and will be ready for use. Each time a container receives
a request, it first checks to see if the JSP file has changed since it was last translated.
If it has, it's retranslated so that the response is always generated by the most
up-to-date implementation of the JSP file. Enterprise application
deployment units in the form of .ear, .war, .rar, etc. will also needs to be loaded
and reloaded at will or as per configured policies. For all of these scenarios, loading,
unloading and reloading is possible only if we have control over the application
server's JVM's class-loading policy. This is attained by an extended class loader,
which can execute the code defined in its boundary. Brett Peterson has given an explanation
of class loading schemas in a J2EE application server context in his article
"
Understanding J2EE Application Server Class Loading Architectures
" at
TheServerSide.com.



Summary



The article talked about how classes loaded into a Java virtual machine are
uniquely identified and what limitations exist when we try to load different
byte codes for classes with the same names and packages. Since there is no explicit class
versioning mechanism, if we want to load classes at our own will, we have to use
custom class loaders with extended capabilities. Many J2EE application servers have a
"hot deployment" capability, where we can reload an application with a new version
of class definition, without bringing the server VM down. Such application servers
make use of custom class loaders. Even if we don't use an application server, we can
create and use custom class loaders to finely control class loading mechanisms in our Java
applications. Ted Neward's book
Server-Based Java Programming
throws light onto the ins and outs of Java class loading, and it teaches those concepts
of Java that underlie the J2EE APIs and the best ways to use them.



References





Binildas Christudas
is a senior technical architect at Software Engineering Technology
Labs (SET Labs) of Infosys.




Posted by 아름프로

Version 1.5.0 or 5.0?

2005. 2. 10. 22:17

    

Version 1.5.0 or 5.0?




Both version numbers "1.5.0" and "5.0" are used to identify this
release of the Java 2 Platform Standard Edition.
Version "5.0" is the product version, while
"1.5.0" is the developer version.
The number "5.0" is used to better reflect the level of maturity,
stability, scalability and security of the J2SE.  


The number "5.0" was arrived at by dropping the leading "1."
from "1.5.0".   Where you might have expected to see 1.5.0, it
is now 5.0 (and where it was 1.5, it is now 5).



"Version 5.0" Used in Platform and Product Names



Version 5.0 is used in the platform and product names as given
in this table:


        

        
        


        
        

        




        

        
        


        
        

Full Name                                                  Abbreviation                                              
Platform name JavaTM 2 Platform Standard Edition 5.0 J2SETM 5.0        
Products delivered
under the platform
J2SETM Development Kit 5.0     JDKTM 5.0          
J2SETM Runtime Environment 5.0 JRE 5.0



Due to significant popularity within the Java developer community,
the development kit has reverted back to the name "JDK" from "Java 2 SDK" (or "J2SDK"),
and the runtime environment has reverted back to "JRE" from "J2RE".
Notice that "JDK" stands for "J2SE Development Kit" (to distinguish
it from the J2EE Development Kit).  The name "Java Development Kit"
is no longer used, and has not been offically used since 1.1, prior
to the advent of J2EE and J2ME.



As before, the "2" in Java 2 Platform Standard Edition indicates the
2nd generation Java platform, introduced with J2SE 1.2.  This generation
number is also used with J2EE and J2ME.



"Version 1.5.0" Used by Developers




J2SE also keeps the version number 1.5.0 (or 1.5) in some places that
are visible only to developers, or where the version number
is parsed by programs.  As mentioned, 1.5.0 refers to exactly the same
platform and products numbered 5.0.  Version numbers 1.5.0 and 1.5 are used at:



      
  • java -version  (among other info, returns  java version "1.5.0")
      
  • java -fullversion  (returns  java full version "1.5.0-b64")
      
  • javac -source 1.5  (javac -source 5  also works)
      
  • java.version  system property
      
  • java.vm.version  system property
      
  • @since 1.5  tag values
      
  • jdk1.5.0  installation directory
      
  • jre1.5.0  installation directory
      
  • http://java.sun.com/j2se/1.5.0  website (http://java.sun.com/j2se/5.0  also works)





Also see:





Posted by 아름프로


JavaTM 2 Platform Standard Edition 5.0 Development Kit (JDK 5.0).
Posted by 아름프로
getResource의 경우..
jar 로 만들시에 문제가 발생할 수 있습니다.

다음 내용을 참조하세요..

http://java.sun.com/docs/books/tutorial/uiswing/misc/icon.html#getresource
Posted by 아름프로
Java Platform Localization Classes
In the Java 2 platform, java.util.Locale represents a specific geographical, political, or cultural region. The string representation of a locale consists of the international standard 2-character abbreviation for language and country and an optional variant, all separated by underscore _ characters. Examples of locale strings include fr (French), de_CH (Swiss German), and en_US_POSIX (United States English on a POSIX-compliant platform).

Locale-sensitive data is stored in a java.util.ResourceBundle. A resource bundle contains key-value pairs, where the keys uniquely identify a locale-specific object in the bundle. A resource bundle can be backed by a text file (properties resource bundle) or a class (list resource bundle) containing the pairs. A resource bundle instance is constructed by appending a locale string representation to a base name.

For more details on internationalization and localization in the Java 2 platform, see

http://java.sun.com/docs/books/tutorial/i18n/index.html

In the Web technology chapters, the Duke's Bookstore example contains resource bundles with the base name messages.BookstoreMessages for the locales en_US and es_ES. See Internationalization Tags (page 703) for information on the JSTL i18n tags.

http://java.sun.com/webservices/docs/1.3/tutorial/doc/JSTL6.html#wp63721




***** 아름다운프로님에 의해서 게시물 복사 + 카테고리변경되었습니다 (2003-12-18 16:33)
Posted by 아름프로

BLOG main image

카테고리

분류 전체보기 (539)
이야기방 (19)
토론/정보/사설 (16)
IBM Rational (9)
U-IT (0)
SOA/WS/ebXML (110)
개발방법론/모델링 (122)
J2SE (34)
Java XML (1)
Java Card (0)
JINI (0)
JAIN (0)
JXTA (0)
Other Java Tech (2)
Swing (0)
개발툴 (2)
SWT/PDE (16)
J2SE(Core) (13)
J2ME (0)
J2EE (60)
DataBase (39)
Open Projects (30)
BP/표준화 (50)
Apache Projects (15)
Web/보안/OS (22)
Tools (7)
AJAX/WEB2.0 (1)
Linux/Unix (1)
영어 (0)
비공개방 (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

달력

«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28

글 보관함

Total :
Today : Yesterday :