자바를 공부하시는분들이 용어를 많이 헷깔려 하더군요...

저역시 그랬구요...

그래서 정리 한번 해봅니다.

자바를 공부하는 사람으로서 꼭 알아야 하는 간단한 용어 몇가지입니다^^


SDK => Standard Development Kit 혹은 Software Development Kit

위의 두가지 표현 모두 맞다고 보시면 됩니다.

어떻게 사용하고, 어떻게 해석하는가에 따라 다르지만 내용은 비슷합니다.

SDK는 자바뿐만아니라 모든 개발언어의 소프트웨어 개발 킷을 말합니다.

프로그램을 개발하려면 개발하는 프로그램이 있어야 겠죠? 그것을 말합니다^^


JDK => Java Development Kit

위에 설명한 SDK가 모든 소프트웨어 개발 킷이라면...  JDK는 말그대로 JAVA 개발 킷을 말합니다. 즉, Java용 SDK의 이름이 JDK라고 표현할수 있죠.

그런데 요즘들어 J2SE Development Kit라고 표현되있는것을 볼수있습니다.

이것은 J2SE의 JDK를 다운받을때 볼수 있는데요...

java.sun.com 홈페이지에 가보면... sun에서는 J2SE의 경우 jdk라 표현하며... 이때 J2SE Development Kit라고 되있습니다. 그리고 J2EE의 경우 j2eesdk라고 되있더군요.

즉, 최근 sun에서는 J2SE의 개발킷을  jdk라고 표현하며... J2EE의 개발킷은 j2eesdk라고 표현하더군요.


J2SDK => Java2 Standard Development Kit 혹은 Java2 Platform Standard Development Kit

위에 JDK설명에서 보시듯이 요즘 J2SE의 개발킷을 JDK라 표현하는데요...

예전에 java2 platform이 출시되었을 당시 java1과 구분하기위해  J2SDK라고 표현 했습니다.

즉, 현제는 java2 platform만 사용하기 때문에 JDK와 동일하다고 보시면 됩니다.


J2SE => Java 2 Standard Edition 혹은  Java2 Platform Standard Edition

J2SE는 말그대로 java의 표준 플렛폼 입니다.


J2ME => Java 2 Micro Edition혹은  Java2 Platform Micro Edition

J2ME는 규모가 작은곳에 프로그램을 개발하기 위한 플렛폼 입니다.

예를들면 PDA를 들수있죠^^


J2EE => Java 2 Enterprise Edition혹은  Java2 Platform Enterprise Edition

J2EE는 웹기반의 엔터프라이즈 어플리케이션을 구축하기 위한 플렛폼 입니다.

대표적으로 EJB가 있죠^^


JRE => J2SE Runtime Environment

JRE는 실행버젼입니다. JDK로 제작한 테스트 프로그램등을 실행할수 있도록 해주죠.

그래서 파일용량이 적은대신 개발할수는 없습니다.

기본적으로 디벨로퍼킷에 JRE가 포함되어 있으므로 따로 설치할 필요가 없습니다.

예를들면 한글뷰어 아시죠?

한글파일을 작성할수는 없지만 읽을수는 있죠.

이것과 비슷합니다^^

출처 : 네이버지식인 오픈사전 노하우 [작성자:cloudyeyes]

URL : http://kin.naver.com/knowhow/entry.php?eid=HMPsi8IAo1iprm9VUPg/vPEBd86+0XuC

'old > JAVA' 카테고리의 다른 글

객체지향 프로그래밍의 4대 특징  (0) 2010.11.10
정규표현식 정리  (0) 2010.08.25
abstract와 interface  (0) 2010.07.01
Scanner, StringTokenizer, DecimalFormat, ChoiceFormat, MessageFormat  (0) 2010.05.25
HashMap, TreeMap, Properties  (0) 2010.05.25
Posted by jazzlife
,

 

내가 객체지향을 공부했어!

객체지향 프로그래밍엔 빠삭해!

XXX 객체지향 언어에 대해서는 모르는 게 없다!

 

이렇게 말할 수 있으려면 객체지향의 4대 특징을 이야기 할 수 있어야 하고 그 객체지향 언어가 어떤 문법을 통해 4대 특징을 지원하는 지 열거할 수 있어야 합니다. 그 만큼 객체지향 프로그래밍의 4대 특징은 객체지향의 핵심중의 핵심입니다.

 

객체지향 프로그래밍의 첫번째 특징은 추상화 (abstraction)입니다. 추상화라고 하는 것은 객체들의 공통적인 특징(속성과 기능)을 뽑아내는 것입니다. , 우리가 구현하는 객체들이 가진 공통적인 데이터와 기능을 도출해 내는 것을 의미합니다.

 

그럼 추상화가 객체지향만의 특징이냐? 그렇지 않습니다. 추상화라고 하는 것은 절차지향 프로그래밍에서도 있어왔습니다. 대표적인 것이 구조체와 같은 사용자 데이터 형입니다. 이것은 데이터를 추상화해서 하나의 새로운 데이터 유형을 만드는 것입니다. 예를 들면 국어, 영어, 수학 점수를 모아 하나의 데이터 형으로 만든다면 아래와 같이 정의할 겁니다.

 

struct Sungjuk

{

  int kor_score;

  int eng_score;

  int math_score;

};

 

Sungjuk이라는 새로운 이름으로 데이터형을 정의하는 데 그 부속데이터로 kor_score, eng_score, math_score를 두고 있습니다. 성적이라는 데이터를 추상화를 통해 정의한 것입니다.

기능의 추상화도 있습니다. 함수가 바로 그것인데, 잘 쓰는 기능을 이름을 붙여 정의하였으니 기능을 추상화 한 것이죠. 여기서 데이터의 추상화와 기능의 추상화에서 알 수 있는 하나의 사실이 있습니다. 추상화라고 하는 것에는 항상 새로운 이름이 붙는다는 점입니다. 따라서 프로그래밍 입장에서 추상화라고 하는 것은 이렇게 정리해 볼 수 있습니다.

 

공통의 속성이나 기능을 묶어 이름을 붙이는 것

 

객체지향 프로그래밍에서 추상화는 그럼 무엇일까요? …

네 생각하는 대로 입니다. 클래스를 정의하는 과정이 바로 추상화라고 할 수 있습니다. 추상화관련 문법은 다음 장에서 다루기로 하고 일단 여기서 추상화 설명을 마치겠습니다.

 

 

두번째 특징은 바로 캡슐화(encapsulation)입니다. 객체지향에서 캡슐화는 데이터 구조' `데이터를 다루는 방법'를 결합시켜 묶는 것을 말합니다. 캡슐형태로 된 알약을 떠 올리시면 됩니다. 캡슐형 알약에는 질환을 치료하는 데 필요한 다른 종류의 약이 적정한 비율로 섞여있는 것을 볼 수 있습니다. 해당 질환을 치료하기 위한 목적으로 하나가 아닌 몇 가지 기능의 약을 하나의 캡슐안에 담은 겁니다.

객체지향에서 캡슐화도 마찬가지 입니다. 특정 객체가 독립적으로 역할을 제대로 수행하기 위해 필요한 데이터와 기능을 하나로 묶어 관리합니다. 객체가 맡은 역할을 수행하기 위한 하나의 목적을 위해 데이터와 기능들을 묶는 것이죠.

 

그런데 캡슐화라는 특징은 다른 의미로도 쓰입니다. , 데이터는 은닉하고 그 데이터를 접근하는 기능(함수)를 밖으로 노출한다는 의미를 나타낼 때 캡슐화라는 용어를 씁니다. 데이터를 기능이라는 캡슐로 보호한다는 것이죠.

 

 

 


위 그림처럼 데이터를 기능으로 보호하여 데이터의 입출력이 기능을 통해 통제되도록 설계하는 것을 말합니다. 역시 자세한 것은 뒤에 설명될 겁니다.

 

 

세번째 특징은 상속성(inheritance)입니다. 객체지향의 꽃입니다. 상속이 없으면 객체지향은 절차지향과 큰 차이가 나지 않습니다. 객체지향 문법이 어렵고 복잡해 질 이유도 없죠. 상속이란 특징을 가지면서 객체지향 언어가 절차지향 언어에 비해 문법의 규모가 2배이상 늘어났습니다.

 

상속이란 상위개념의 특징을 하위 개념이 물려받는 특징을 말합니다. 예를들어 남학생이라는 단어에는 학생이라는 단어의 특징을 물려받고 있습니다. 개념적 특징이 상속되는 것이죠. ‘학생이 갖는 특징을 그대로 계승하면서 남학생만 갖는 특징을 부가하여 남학생의 전체 특징이 형성됩니다. 이 개념을 프로그래밍에 도입한 것인데 하나의 클래스가 가지고 있는 특징(데이터와 함수)들을 그대로 다른 클래스가 물려주고자 할 때 상속성의 특징을 사용합니다.

 

 

네번째 특징은 다형성(polymorphism)인데 객체지향 개념 중 가장 까다롭고 4대 특징중에 가장 이해하기 어려운 특징입니다. 알았다고 해도 코딩으로 잘 활용이 안 되는 특징이기도 하죠. 이것을 잘 이해하고 활용한다면 객체지향 언어를 제대로 쓰는 것으로 봐도 무방할 정도입니다.

 

다형성의 의미는 약간 다른 방법으로 일을 하는 함수를 동일한 이름으로 호출해 주는 것을 말합니다. 이해가 잘 안 되죠?  예를 들어 보겠습니다. 홍길동이란 이름의 학생과 김철수라는 학생이 있다고 가정해 봅시다. 그런데 선생님이 홍길동을 바라 보면서 학생! 칠판 지워라고 명령을 했다고 합시다. 홍길동은 나름의 방법으로 칠판을 지울 겁니다. 다시 선생님이 김철수를 바라보면서 학생! 칠판 지워!’라고 명령했을 때 김철수도 자신만의 방법으로 칠판을 지울 겁니다. 그런데 홍길동이 지웠던 방식과는 다르겠죠? ‘학생! 칠판 지워.’라는 표현은 같지만 칠판을 지우는 행위는 다르게 나타나고 있습니다. 이것이 바로 다형성입니다. ‘학생! 칠판 지워.’라는 명령이 다양한 결과로 나타나기 때문에 이것을 다형성이라고 하는 것입니다.

 

프로그래밍 입장에서 다형성을 해석해 본다면 명령의 해석을 연결된 객체에 의존하는 것으로 정의할 수 있습니다. 이것도 나중에 자세히 코딩을 통해 설명할 것입니다.

 

 

이번 시간은 객체지향 프로그래밍 4대 특징의 정의 정도만 이해하시면 되겠습니다. 추상화를 이용한 프로그래밍 문법은 다음 시간에 하도록 하죠.

Posted by jazzlife
,

정규표현식 정리

old/JAVA 2010. 8. 25. 15:03
PHP 정규표현식 정리  

글쓴이 : 오렌지블루
  저작권자 이메일 :

출처 : codelib.co.kr
  작성일 : 2002/03/02 11:54:16

  
정규표현식이라고 불리우는 Regular expression 에 대한 phpbuilder.com 의 포럼부분 을 토대로 첨삭된 문서이다. 대부분의 프로그래밍에서 많이 필요로 하는 정규표현식 의 간략한 문법에 대해 소개하고 있다.
------------------------------------------------------------
------------------------------------------------------------

정규표현식 (Regular expression)

--------------------------------------------------------------------------------
정규표현식 (Regular 예pression)

정규표현식은 문자열의 일정한 패턴을 찾던지 치환하여 주는 기능을 가지고 있다.
메일 주소검사라던지, 소수점 몇째자리 까지 끊어서 보여주기 등.. 더욱더 복잡한
문자열도 이 정규표현식으로 처리할수 있다....
이는 프로그램시에 많은 일을 쉽게 처리하여 준다 (대부분 내장함수에도 있네요...)
특히 웹에서는 폼값을 처리할때 특정폼의 형식이 원하는 형식에 맞는지 검사할때
많이 쓰일수 있다. 정규표현식은 거의 모든 언어에서 지원하지만 사용법은 조금씩
다르다. 하지만 크게 다르지 않으므로 익혀놓으면 많은 도움이 되리라 생각된다.

**아래의 글은 몇가지 문서를 참고하였으며 정규표현식의 모든것을 포함하지는
않는다. (기본은 phpbuilder.com의 컬럼란의 내용이다)
============================================
편의상 반말을 한것에 대하여 양해를 구합니다.
============================================

정규표현식은 보통 eregi, eregi_replace, ereg, ereg_replace, 또는 perl 의 함수패턴을
그대로 사용할수 있도록 해놓은 함수 preg_match, preg_split, preg_quote 등의 함수
를 사용한다. (아마 perg 는 php 버전이 3.0.9 이상에서 사용가능할겁니다)

예) 사과라는 문자열을 배라는 문자열로 치환한다.
$string ="이것은 사과 입니다";
ereg_replace("사과","배",$string);


1. ^ 와 $ 의 사용의 예

'^' 는 바로 문자뒤의 문자열로 시작 됨을 가르킨다.
"^The" : 는 "The"로 시작 하는 문자를 말한다.

'$' 는 문자열의 맨 마지막을 가르킨다.
"of despair$" : 는 "of despair"로 끝나는 문자열이다.

"^abc$" : 는 hello로 시작해 hello로 끝나는 경우 이므로 "abc" 만 해당된다..


2. '.' '*' '+' '?' 의 사용법

'.' 은 어떤 문자든지 임의의 한문자를 말한다.꼭 하나의 문자가 있어야 한다.
예) "x.z" 는 xyz, xxz, xbz 등이고 xz난 xyyz는 안된다.

'*' 는 바로 앞의 문자가 없거나 하나 이상의 경우를 말한다.
예) "ab*" 는 a, abc, ab, abbbb 등을 말한다.

'+' 는 바로 앞의 문자를 나타내면 꼭 1나 이상이어야 한다.
예) "ab+" 는 abc, abbb 등이고 a는 되지 않는다.

'?' 는 바로 앞의 한문자가 있거나 없는것을 말한다. 단지 한문자 만이어야 한다.
예) "ab?" 는 a 또는 ab 를 나타낸다.


3. [], {} 와 () 그리고 |

3-1 '[]' 는 [] 안에 존재하는 문자들중 한 문자만을 나타낸다.
예) [abc] 는 a 또는 b 또는 c 중에 한문자를 나타낸다. 여기서 '-'를 사용할땐 범위를 나타낸다.
즉 [ a-f ] 는 [abcdf] 와 같은것을 나타낸다.
문자클래스 오퍼레이터라는 것에 대해 잠시..
유사한 성격의 문자들을 사용자가 알아보기 쉽게 단어로 그룹을 지었다고 보면 된다.

alnum : 알파벳과 숫자
alpha : 알파벳
blank : 스페이스나 탭 (시스템에 의존적임)
cntrl : 아스키코드에서의 127 이상의 문자와 32 이하의 제어문자
(한글의 첫째바이트가 127 이상이므로 제어문자로 취급됨 :()
digit : 숫자
graph : 스페이스는 제외되고 나머지는 'print' 항목과 같음.
lower : 소문자
print : 아스키코드에서 32에서 126까지의 찍을 수 있는 문자
punct : 제어문자도 아니고 알파벳.숫자도 아닌 문자
space : 스페이스, 케리지 리턴, 뉴라인, 수직 탭, 폼피드
upper : 대문자
xdigit : 16진수, 0-9, a-f, A-F

[[:alnum:]]은 [a-zA-Z0-9] 와 같은 의미다.
[[:alpha:]]은 [a-zA-Z] 와 같은 의미다.
문자열 오퍼레이터는 [] 사이에서만 효력을 발휘한다.
그리고 반대의 의미도 가능하다.
[^[:alnum:]] 은 알파벳과 숫자의 조합이 아닌것을 말한다.
[^a-zA-Z0-9] 와 같이 사용될수도 있다.



'3-2 {}'는 {} 앞에 있는 문자나 문자열의 개수를 정하는 것이다.

예) "ab" 는 "abb"를 나타낸다. 즉 b의 개수가 2개를 나타낸다.
"ab{2,}" 는 abb, abbbbb 등 b의 개수가 2개 이상을 나타낸다.
"ab{3,5}" 는 abbb, abbbb, abbbbb 와 같이 b가 3개에서 5개 까지를 나타낸다.


3-3 '()' 는 ()안에 있는 글자들을 그룹화 한다.

예) a(bc)* 는 a, abc abcbc 등 'bc'가 없거나 하나 이상인 경우이다.
"a(bc)" 는 abcbc 를 나타낸다.


3-4 '|' 는 OR 연산자 기능을 한다.

"a|b" 는 a 또는 b 둘중 하나를 나타낸다.

참고할것은 기호인데 이것은 . (, ) 등 단지 다음에 오는것이 문자라는것을
의미한다. 어떤한 처리도 없이 문자로만 인식한다.
{1,3} 하고 하면 {1,3} 와는 다르다.

4. 기초 활용

"a(bc)*" 는 a라는 문자를 포함하고 bc라는 문자열이 없거나 계속반복되는 문자열이다.
이것은 a, abc ,abcbc abcbcbc.... 등의 문자열을 의미한다.

"a(bc){1,5}" 는 a 라는 문자를 포함하고 bc 라는 문자를 묶은 형태인데. bc 라는 문자가
한번에서 5번까지를 말한다. --말이 더 어렵다....
이것은 abc,abcbc,abcbc,abcbcbc,abcbcbcbc,abcbcbcbcbc 의 문자열을 의미한다.

^[1-9][0-9]*$ 는 자연수를 표시할수 있다.
^(0|[1-9][0-9]*)$ 는 0을 포함하는 자연수
^(0|-?[1-9][0-9]*)$ 정수표시
^[0-9]+(.[0-9]+)?$ 소숫점 표시
^[0-9]+(.[0-9])?$ 소수점 둘째자리 까지
^[0-9]+(.[0-9]{1,2})?$ 소수점 둘째자리나 첫째자리
^[0-9]{1,3}(,[0-9])*(.[0-9]{1,2})?$ 돈의 표시...
(센트까지 표시가능 예 2,200.20 : 이천이백이십센트 또는 이천이백이십전 맞나?)

5. 복합활용

5-1 메일 주소 체킹..

5-1-1 : 유저명@도메인명

유저명 : 대문자, 소문자, 숫자 그리고 '.' '-' '_' 을 가질 수있지만 . 로 시작해서는 안된다.
[_0-9a-zA-Z-]+(.[_0-9a-zA-Z]+)*
이때에는 eregi 를 사용할때까 아닌 ereg 를 사용할때이다. eregi 함수는 대소문자구분이 없다.
^[_a-z0-9-]+(.[_a-z0-9-]+)*$ eregi 함수를 사용할때...

5-1-2 : 도메인 : 유저명과 기본적으로는 같지만 _ 가 없다.
^[a-z0-9-]+(.[a-z0-9-]+)*$

5-1-3 : 메일 주소 체킹
위의 것의 조합이다.

^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$

5-2 URL 에 http:// 붙여주기

URL 은 대문자, 소문자, 숫자 ,'.','_','=','&','?','~','@','/','+' 를 사용 할수 있다
http://([0-9a-zA-Z./@~?&=_]+) 가 된다.


$add="www.codelib.co.kr";
$pattern ="([0-9a-zA-Z./@~?&=_]+)";
$link =ereg_replace($pattern, "http://1" $add);
echo ("$link");

의 결과 $link 는 다음처럼 변경 된다.
http://www.codelib.co.kr
와 같이 된다. 참고로 1 은 첫번째 괄호안의 값을 말한다. 2는 2번째..

몇가지 복잡한 정규표현식을 풀다보면 이해하는데 도움이 될것이다 '  

출처 : koreaphp.co.kr 

[출처] PHP 정규표현식 정리 |작성자 뮤즈

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


Regular Expressions

  1. 문자 집합 : [] - 대괄호 사이에 찾고자 하는 문자들의 집합을 표기한다
    • 예)
      • [0-9] : 0부터 9까지의 숫자 한 문자
      • [Aa] : A 혹은 a에 대응하는 한 문자
    • "-"(하이픈)은 문자 집합인 대괄호 안에서 만 문자의 범위를 지정하는 기호로 쓰인다.
  2. 제외 문자 : ^ (캐럿) - ^기호 뒤의 문자를 제외한 문자 (집합기호 - [] - 안에서 쓰일때)
    • 예)
      • ns[^0-9] : nsx - ns다음의 x가 숫자가 아닌 한 문자에 대응
  3. 메타 문자 : 정규표현식에서 특별한 의미를 가지는 문자

    • 정규표현식에서 메타문자 및 기호문자를 찾고자하는 문자에 대응하려면 "\"(escape)를 붙혀 사용한다.

    • 모든 문자 : .(마침표) - 모든 문자에 대응되는 한 문자

    • 공백 문자 : \n, \r, \t, \f-form feed, \v-vertical tab

    • 특별한 문자 형태

      • 숫자와 숫자 아닌문자 : \d - [0-9], \D - [^0-9]

      • 영숫자 문자와 영숫자 문자가 아닌 문자 : \w - [a-zA-Z0-9_], \W - [^a-zA-Z0-9_]

      • 공백문자와 공백이 아닌문자 : \s - [\f\n\r\t\v], \S - [^\f\n\r\t\v]

      • 16진수 8진수 : \x, \0

  4. 반복찾기
    • + : 한 문자 이상 - + 기호 앞으 문자가 하나 이상 반복
    • * : 문자가 없거나 하나 이상 반복
    • ? : 문자가 없거나 하나와 대응하는 문자   예) https?// - s가 없거나 한번 있는 경우와 대응
  5. 반복회수 지정하기 : {} (중괄호) - 중괄호 앞의 문자에 대하여 반복회수 지정
    • 반복회수 지정 : {반복회수} - 저정된 회수만큼 반복하는 경우 대응
      • 예)
        • #[0-9A-Fa-f]{6} - 16진수 RGB표기
    • 최소, 최대 반복회수 지정 : {최소, 최대} - 최소번 또는 최대번만 반복되는 경우 대응, 최소값에 0과 최대값의 생략 가능
      • 예)
        • \d{1,2}[-\/]\d{1,2}[-\/]\d{2,4} - -또는 / 구분의 날짜 표기
  6. greedy와 lazy 수량자
    • 탐욕적 수량자 : +, *, {n,}
    • 게으른 수량자 : +?, *?, {n,}?
    • 예) abcd <b>xxx</b> and <b>yyy</b> efgh
      • greedy : <[Bb]>.*</[Bb]> --> <b>xxx</b> and <b>yyy</b>
      • lazy : <[Bb]>.*?</[Bb]> --> <b>xxx</b> 와 <b>yyy</b>
  7. 단어 경계 지정
    • 단어 사이의 공백 : \b - 공백문자(space)와 일치하지만 공백을 일치하는 문자로 지정하지는 않는다. (\B - \b와 반대) --> 단어 사이의 구분자로 쓰임
      • 실제 공백 문자를 찾을 때는 [ ]또는 \s를 활용한다.
    • 시작 문자 지정 : ^(캐럿) - 제외 문자와 달리 표현식의 처음에 사용되어 다음에 나오는 문자를 시작하는 문자로 지정할 수 있다.
    • 마지막 문자 지정 : $ - 앞에 나온 문자가 마지막에 일치할때
    • 다중행 모드 : (?m)
      • 지정한 문자열을 줄단위로 분리하여 표현식을 검색한다.
      • 표현식의 가장 앞에 써준다.
      • 다중행 모드 지정시 ^와 $를 지정단 문자열의 줄단위로 검색하는 것이 가능하다.
    • 예) 라인단위 주석(//) 문자로 부터 해당 라인의 끝까지
      • (?m)^//.*$
  8. 하위 표현식 : () - 괄호
    • 표현식 일부를 괄호로 묶어준다.
    • 중첩 하위 표현식 : 괄호안에 괄호...
    • or 연산자 : | - | 기호의 좌우 둘중 하나가 일치하는 경우
    • 예) 아이피 형식의 문자열
      • (\d{1,3}\.){3}\d{1,3}
      • (((\d{1,2})|(1\d{2}))|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2}))|(2[0-4]\d)|(25[0-5]))
  9. 역참조 : \1 ~ \9
    • 표현식 중 하위 표현식의 순서와 지정한 번호가 해당 하위 표현식과 일치한다.
    • 0번을 지정하면 해당 표현식 전부와 일치한다.
    • 예) html의 <H1~6>태그의 내용 찾기
      • <Hh([1-6])>.*?</Hh\1>
  10. 전방탐색과 후방탐색 : 하위표현식으로 표현
    • 전방탐색 : ?= - 지정한 전방 탐색 기호의 다음 표현식으로 부터 앞에 나오는 일치하는 문자를 찾는다.
    • 후방탐색 : ?<= - 지저한 후방 탐색 기호의 다음 표현식으로 부터 뒤에 나오는 일치하는 문자를 찾는다.
    • 예) html tag기회 내의 내용
      • (?<=<[Tt][Ii][Tt][Ll][Ee]>).*?(?=</[Tt][Ii][Tt][Ll][Ee]>)
    • 부정형 전/후방 탐색 : 전방 - ?!, 후방 - ?<!
      • 예) $로 시작하지 않는 숫자
        • \b(?!\$)\d+\b
  11. 조건 달기 : ?
    • ? 앞의 문자(표현식)가 없거나 한번 일치할때 해당하는 앞으 문자(표현식)과 일치한다.
    • 전후방 탐색(?=, ?<=)의 뒤에 나오는 표현식과 일치할때...
    • 역참조 조건 : (?(backreference)true), (?(backreference)true|false)
      • backreference는 역참조 대상의 하위 표현식이며, \를 붙이지 않고 해당 하위 표현식 순서에 해당하는 번호를 지정한다.
        • 예) IMG 태그나 이미지 태그를 싸고 있는 A태그
          • (<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>(?(1)\s*</[Aa])>)
        • 예)
          • (\()?\d{3}(?(1)\)|-)\d{3}-\d{4}
    • 전방 탐색 조건 : (?(?=condition)expressions)
      • 예)
        • \d{5}(?(?=-)-\d{4})

* 유용한 정규 표현식 예

- IP : (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))

- URL : https?://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?

- Email : (\w+\.)*\w+@(\w+\.)+[A-Za-z]+

- HTML 주석 : <!-{2,}.*?-{2,}>

- 주민등록번호 : \d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])-[1-4]\d{6}

- 한글 : [가-힣]

- 유니코드 : \ucodenumber

Posted by jazzlife
,

JNI(Java Native Interface)

플랫폼 독립성을 버리고, 기능을 취한다.

자바 프로그램을 작성하다보면, 부득이하게 시스템 의존적 코딩을 필요로 하는 때가 있다. 하지만, 자바로서는 그러한 욕구를 감당할 수는 없다. 따라서, 자바의 클래스 파일이 C/C++의 함수를 호출하여, 그 결과만 되돌려받게 하는 것도 한 방법이다. 그렇지만 이 자체로서 이미 플랫폼 독립적이라는 특성은 사라졌다고 볼 수밖에 없다.

프로그램 작성

첫째 단계, 자바 프로그램 작성

우선, Native접근이 필요한 메쏘드만 native 키워드를 사용해 구현하지 않은 채 그대로 두고, 나머지는 모두 구현한 후, 컴파일한다.

    public class Hello {
        public native void getHello();

        static {
            System.loadLibrary("hello");
        }
       
        public static void main(String[] args) {
            new Hello().getHello();
        }
    }

    javac Hello.java

public native void getHello() : getHello 함수가 native method라는 것을 의미한다.

static {
        System.loadLibrary("hello");
}

이것은 공유 라이브러리를 실행시 로드하는 코드로 반드시 static 초기화에 포함되어야 한다. 이것은 플랫폼에 따라 다르게 행동하는데, 만일 Win32이면, hello.dll을, 솔라리스이면, libhello.so라는 이름의 라이브러리를 찾는다.

둘째 단계, C프로그램을 위한 헤더 파일 생성

javah와 -jni옵션을 이용하여, 헤더파일을 생성해 보자.

    javah -jni Hello

생성된 헤더 파일 Hello.h는 다음과 같다.

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>

    /* Header for class Hello */

    #ifndef _Included_Hello
    #define _Included_Hello
    #ifdef __cplusplus
    extern "C" {
    #endif


    /*
     * Class:     Hello
     * Method:    getHello
     * Signature: ()V
     */


    JNIEXPORT void JNICALL Java_Hello_getHello
      (JNIEnv *, jobject);

    #ifdef __cplusplus
    }
    #endif
    #endif

여기서 생성된 함수 이름에 주목해 보자. '_'를 구분자로 크게 몇 부분으로 나뉘어져 있다.

    • Java : 항상 앞에 붙는다.
    • Hello : 클래스의 이름
    • getHello : 메쏘드의 이름

셋째 단계, 함수를 구현한다.

HelloImpl.c라는 이름으로 함수를 구현해 보자.

    #include <jni.h>
    #include "Hello.h"
    #include <stdio.h>

    JNIEXPORT void JNICALL Java_Hello_getHello(JNIEnv *env, jobject obj)
    {
        printf("OOPSLA\n");
        return;
    }

넷째 단계, C파일을 컴파일하여, 공유 라이브러리를 생성한다.

이때, 비주얼 C++을 이용할 경우 다음과 같은 옵션을 준다.

cl /I본인의 자바 디렉토리)\include /I(본인의 자바 디렉토리)\include\win32 -LD HelloImp.c -Fehello.dll

솔라리스에서 컴파일할 경우 다음과 같은 옵션을 준다.

cc -G -I(자바 홈 디렉토리)/include -I(자바 홈 디렉토리)/include/solaris HelloImp.c -o libhello.so

마지막 단계, 프로그램을 실행한다.

    java Hello

실행 결과:

    OOPSLA

자바의 타입과 C++/C의 타입 매핑 문제

네이티브 메쏘드를 호출하는 것까지는 좋다. 하지만, 그 결과값이 있을 경우에는 타입의 괴리(Impedence)가 존재할 수밖에 없다. 따라서, jni.h에는 자바의 타입을 흉내낼 수 있는 여러 가지 타입을 정의해 놓았다.

Primitive Types

네이티브 메쏘드에서는 보통 자바의 타입 이름 앞에 j가 붙은 이름을 가진 타입을 사용함으로써, 마치 자바 프로그램을 작성하는 듯이 프로그램할 수 있다. 예를 들어, boolean은 jni.h에 jboolean이라는 이름의 타입과 매핑된다.

  • jboolean  : 자바의 boolean(8비트) - typedef unsigned char   jboolean
  • jbyte : 자바의 byte(8) - typedef signed char jbyte(WIN32의 경우이다. - System Dependent)
  • jchar  : 자바의 char(16) - typedef unsigned short  jchar
  • jshort : 자바의 short(16) - typedef short  jshort
  • jint : 자바의 int(32) - typedef long jint(WIN32의 경우이다. - System Dependent)
  • jlong : 자바의 long(64) - typedef __int64 jlong(WIN32의 경우이다. - System Dependent)
  • jfloat : 자바의 float(32) - typedef float jfloat
  • jdouble : 자바의 double(64) - typedef double  jdouble;
  • void : 자바의 void

위의 리스트에서, 오른쪽은 실제 jni.h가 이 타입들을 어떻게 정의하고 있는지를 보여 준다. 여기서, jbyte, jint, jlong은 시스템에 따라 적용할 타입이 변경될 소지가 있으므로, WIN32의 경우, 자바디렉토리\include\win32\jni_md.h에 정의되어 있다. 솔라리스인 경우에는 참고로 다음과 같다.

    #ifdef _LP64 /* 64-bit Solaris */
    typedef int jint;
    #else
    typedef long jint;
    #endif
    typedef long long jlong;
    typedef signed char jbyte;

객체 타입

이 경우에도 비슷하다. 일반 객체는 jobject타입으로 통용하고, 나머지 특수한 클래스에 대해 매핑되는 타입을 두기로 한다.

  • jobject : 모든 자바 객체로 뒤에 나열된 모든 타입의 슈퍼 타입이다.
  • jstring : 자바의 java.lang.String클래스이다.
  • jclass : 자바의 java.lang.Class클래스이다.
  • jarray : 자바의 배열이다.
  • jthrowable ; 자바의 java.lang.Throwable 예외 사항이다.

배열

기타, 기본 타입의 배열을 위한 배열 타입도, 하나의 클래스로 정의되어 있다.

    jbooleanArray;
    jbyteArray;
    jcharArray;
    jshortArray;
    jintArray;
    jlongArray;
    jfloatArray;
    jdoubleArray;
    jobjectArray;


함수와 메쏘드간의 인자 전달

문제는 jstring을 비롯한 타입들은 실제 printf문 같은 곳에서 직접 쓰일 수 없다는 것이다. 이것들은 다시, C/C++의 타입으로 변환되어 사용되어야 한다. 이것에 관한 여러 함수들이 JNIEnv라는 구조체에 정의되어 있다.

예를 들어, String객체를 C메쏘드에 넘기도록 앞의 Hello.java를 수정해 보자. 자바 소스는 단순히 선언을 바꾸는 것으로 끝난다.

    public native void getHello(String name);

재컴파일과, javah를 이용해 만든 새로운 헤더 파일을 이용해 HelloImpl.c를 새로 작성해 보면,

    JNIEXPORT void JNICALL Java_Hello_getHello(JNIEnv *env, jobject obj,jstring name)
    {
          char *str_name = (*env)->GetStringUTFChars(env, name, 0);
          printf("Hello %s\n",str_name);
          (*env)->ReleaseStringUTFChars(env, name, str_name);
          return;
    }

이와 같이, JNIEnv의 멤버 함수로부터 도움을 받아야 한다.

이제 각 타입에 대해 인자 전달과 결과값 반환 방법을 알아 보자.

Primitive Types

기본 타입의 경우에는 다음과 같이 기존의 C/C++타입중 호환되는 타입의 재명명이므로, 그다지 인자 전달에 문제가 없다.

    typedef unsigned char   jboolean;
    typedef unsigned short  jchar;
    typedef short           jshort;
    typedef float           jfloat;
    typedef double          jdouble;

    WIN32:
    typedef long jint;
    typedef __int64 jlong;
    typedef signed char jbyte;

다만, boolean의 경우에는 true/false값이 다음과 같이 전달된다.

    #define JNI_FALSE 0
    #define JNI_TRUE 1

예를 들어, boolean타입의 인자를 주고, 반환받는 경우,

    Hello.java:
    Hello h = new Hello();
    System.out.println("h.getBoolean(true) = "+h.getBoolean(true));    // 결과 : true

    HelloImpl.c:
    JNIEXPORT jboolean JNICALL Java_Hello_getBoolean(JNIEnv * env, jobject jobj, jboolean jbool)
    {
           ......
            return JNI_TRUE;
    }

배열 타입

각 기본 타입에 따라 그 배열을 다룰 수 있는 배열 클래스가 제공된다.

    jarray
    jbooleanArray
    jbyteArray
    jcharArray
    jshortArray
    jintArray
    jlongArray
    jfloatArray
    jdoubleArray

모든 배열 클래스들은 jarray 클래스의 하위 클래스이다.

배열의 길이 파악

모든 배열의 길이를 알아낼 수 있는 함수는 다음과 같다.

    jsize GetArrayLength(JNIEnv *, jarray array)

(jsize는 jint와 동일하다)

자바의 배열을 C의 배열로 변환하는 함수

각 타입마다 자바 타입의 배열을 C타입으로 변환시켜 주는 함수가 있다.

  • jboolean * GetBooleanArrayElements(JNIEnv *env,jbooleanArray array, jboolean *isCopy)
  • jbyte * GetByteArrayElements(JNIEnv *env,jbyteArray array, jboolean *isCopy)
  • jchar * GetCharArrayElements(JNIEnv *env,jcharArray array, jboolean *isCopy)
  • jshort * GetShortArrayElements(JNIEnv *env,jshortArray array, jboolean *isCopy)
  • jint * GetIntArrayElements(JNIEnv *env,jintArray array, jboolean *isCopy)
  • jlong * GetLongArrayElements(JNIEnv *env,jlongArray array, jboolean *isCopy)
  • jfloat * GetFloatArrayElements(JNIEnv *env,jfloatArray array, jboolean *isCopy)
  • jdouble * GetDoubleArrayElements(JNIEnv *env,jdoubleArray array, jboolean *isCopy)

정수의 경우를 예로 들어 보자.

       jsize iSize = (*env)->GetArrayLength(env,jiarray);
       jint *iArray = (*env)->GetIntArrayElements(env,jiarray,0);

       for(i=0; i < iSize; i++) {
                printf("iArray[%d] = %d\n",i,iArray[i]);
                iArray[i]++;
       }
       (*env)->ReleaseIntArrayElements(env,jiarray,iArray, 0);

 자바의 배열을 JNI에서 사용할 경우, 이것은 현재의 실행 루틴을 수행하는 쓰레드가 이 배열 객체에 대해 PIN 연산을 수행하거나, 아니면 전체의 로컬 복사본을 사용하게 되는 것이다. 이로 인해, 이 연산의 반대 급부로 반드시 UNPIN연산에 해당하는 ReleaseIntArrayElements가 불려지는 것이 좋다.

  • void ReleaseBooleanArrayElements(JNIEnv *env,jbooleanArray array,  jboolean *elems,  jint mode)
  • void ReleaseByteArrayElements(JNIEnv *env,jbyteArray array, jbyte *elems, jint mode)
  • void ReleaseCharArrayElements(JNIEnv *env,jcharArray array, jchar *elems,  jint mode)
  • void ReleaseShortArrayElements(JNIEnv *env,jshortArray array, jshort *elems,  jint mode)
  • void ReleaseIntArrayElements(JNIEnv *env,jintArray array, jint *elems, jint mode)
  • void ReleaseLongArrayElements(JNIEnv *env,jlongArray array, jlong *elems, jint mode)
  • void ReleaseFloatArrayElements(JNIEnv *env,jfloatArray array, jfloat *elems, jint mode)
  • void ReleaseDoubleArrayElements(JNIEnv *env,jdoubleArray array, jdouble *elems, jint mode)

이 외에도 다음과 같은 함수들이 있다.

  • jdoubleArray NewDoubleArray(jsize len)를 비롯해 각 기본 타입마다 새로운 자바 배열을 생성할 수 있다.
  • void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, jboolean *buf)를 비롯해 각 기본 타입마다 Sub배열을 획득할 수 있는 함수가 제공된다.

자바 객체의 사용

네이티브 코드 내에서 자바 객체를 사용할 수도 있다. 즉 콜백과 비슷한 형식을 지원한다. private영역까지 접근할 수 있다.

자바 객체의 클래스 정보 얻기

일단, 인자로 넘겨지는 자바 객체에 대한 클래스 정보를 획득하는 함수가 제공된다.

    jclass cls = (*env)->GetObjectClass(env, jobj);

여기서 주의할 것은 반환값으로 돌아오는 cls의 레퍼런스값은 오직 이 네이티브 메쏘드가 수행이 끝날 동안에만 유효하다는 것이다.

자바 객체 및 클래스 타입의 래퍼런스는 네이티브 메쏘드 실행시마다 결정되므로, 한 번 실행해 얻은 레퍼런스를 다음번 메쏘드에서 다시 사용하려는 것은 잘못된 것이다.

따라서, 원칙적으로 객체 레퍼런스 변수를 전역 변수로 할당하는 것은 위험한 일이다. 하지만, 꼭 허용되지 않는 것은 아니다. 전역 레퍼런스로 지정해 줄 수 있는 함수가 있다.

     jobject NewGlobalRef(JNI_Env* env, jobject lobj)



네이티브 코드를 호출한 객체의 메쏘드에 대한 ID얻기

객체의 메쏘드를 호출하기 위해 그 메쏘드의 ID를 획득해야 한다. 이것은 메쏘드의 이름과 시그너쳐를 이용하는데, 이름은 별 무리가 없겠으나, 시그너쳐는 까다롭다.

시그너쳐는 메쏘드의 인자 리스트와 반환 타입 정보를 스트링화한 것으로, 다음과 같은 규칙이 있다.

  • 시그너쳐 : "(인자 리스트)반환값"으로 이루어진 스트링이다.
  • 인자리스트의 인자들은 아래의 타입 기호에 따라 표기되며, 서로 ';'으로 구분된다.
  • 반환값 역시 타입 기호에 따라 표시된다.

타입 기호는 다음과 같다. 이것은 자바 가상 머신 스펙에서 클래스 파일 포맷 부분에 등장하는 기호와 동일하다.

    Z :  boolean  
    B :  byte
    C :  char
    S :  short
    I  :  int
    J :  long
    F :  float
    D : double

  • 이들의 배열은 이들의 타입 기호 앞에 '['를 붙인다. 즉 int 배열은 [I가 된다.
  • 클래스 타입의 경우, L뒤에 클래스명을 패키지명까지 포함해 나열하면 된다. 즉, String클래스인 경우, Ljava.lang.String이다.

이것은 수작업으로 할 경우, 실수가 많을 수 있으나, javap를 이용해, 쉽게 기호화된 시그너쳐를 확인할 수 있다.

    javap -s -p Hello

    Compiled from Hello.java
    class Hello extends java.lang.Object {
        static {};
            /*   ()V   */
        Hello();
            /*   ()V   */
        public static void coo(java.lang.String, java.lang.String);
            /*   (Ljava/lang/String;Ljava/lang/String;)V   */
        private void foo(java.lang.String, java.lang.String);
            /*   (Ljava/lang/String;Ljava/lang/String;)V   */
        public native boolean getBoolean(boolean);
            /*   (Z)Z   */
        public native byte getByte(byte);
            /*   (B)B   */
        public native char getChar(char);
            /*   (C)C   */
        public native double getDouble(double);
            /*   (D)D   */
        public native float getFloat(float);
            /*   (F)F   */
        public native java.lang.String getHello(java.lang.String);
            /*   (Ljava/lang/String;)Ljava/lang/String;   */
        public native int getInt(int);
            /*   (I)I   */
        public native int getIntArray(int[])[];
            /*   ([I)[I   */
        public native long getLong(long);
            /*   (J)J   */
        public native short getShort(short);
            /*   (S)S   */
        public static void main(java.lang.String[]);
            /*   ([Ljava/lang/String;)V   */
    }

이것은 다음과 같이 Hello클래스에 두 메쏘드를 추가한 후의 javap결과이다.

       private void foo(String str,String str1) {
            System.out.println("Hello.foo() = "+str+str1);
        }

        public static void coo(String str,String str1) {
            System.out.println("Hello.coo() = "+str+str1);
        }

이제 foo메쏘드의 ID를 획득해 보자.

    // 클래스 정보 획득
    jclass cls = (*env)->GetObjectClass(env, obj);

    // 메쏘드 ID
    jmethodID fooM = (*env)->GetMethodID(env, cls, "foo", "(Ljava/lang/String;Ljava/lang/String;)V");

    // 그런 메쏘드가 없으면, 0반환
    if(fooM == 0) {
        printf("Method foo isn't found\n");
    }
    else {
               ......
    } 


인자 생성 및 메쏘드 호출

이제 메쏘드를 호출하는 일이 다음 순서가 되겠다. 물론 여기에 해당되는 함수들이 제공되는데, 이 함수들을 통해, 클래스 내의 메쏘드를 호출하므로, 메쏘드 ID와 더불어 메쏘드의 인자들을 리스트화해서 보내야 한다. 두 가지 방법이 있다.

  • C의 va_list구조체를 이용한다.
  • jvalue 유니온를 이용한다.

여기서는 jvalue 유니온을 이용해 보자. 그 구조는 다음과 같다.

    typedef union jvalue {
        jboolean z;
        jbyte    b;
        jchar    c;
        jshort   s;
        jint     i;
        jlong    j;
        jfloat   f;
        jdouble  d;
        jobject  l;
    } jvalue;

그러면, 스트링 두 개를 인자로 받는  foo메쏘드를 호출해 보자. String은 객체이므로, l에 스트링 객체의 레퍼런스를 할당하면 된다.

    jvalue* args;
    .......

    args = (jvalue*)malloc(sizeof(jvalue)*2);
    args[0].l = (*env)->NewStringUTF(env,"oops");
    args[1].l = (*env)->NewStringUTF(env,"la");
    (*env)->CallVoidMethodA(env, obj, fooM,args );   // JNIEnv, jobject, Method ID, jvalue

여기에서는 foo가 void 타입이므로,  CallVoidMethodA가 쓰였지만, 이 외에에도 반환값에 따라 여러 함수가 제공된다. 이들의 인자는 위와 동일하다.

  • jboolean CallBooleanMethodA
  • jbyte CallByteMethodA
  • jchar CallCharMethodA
  •  jshort CallShortMethodA
  •  jint CallIntMethodA
  •  jfloat CallFloatMethodA
  •  jdouble CallDoubleMethodA

참고로, va_list를 이용하여 인자를 전달하는 함수들은 A로 끝나지 않고, V로 끝나는데, 역시 마지막 인자만 va_list타입으로 수정해 주면 된다.


정적 메쏘드 호출

정적 메쏘드 또한 호출할 수 있는 함수가 따로 있다.

메쏘드 ID : GetStaticMethodID함수 이용

    jMethodID cooM = (*env)->GetStaticMethodID(env, cls, "coo", "(Ljava/lang/String;Ljava/lang/String;)V");
    if(cooM == 0) {
            printf("Method foo isn't found\n");
        }
    else {  .....
    }

인자 형성 방법은 동일하다.

메쏘드 호출 : CallStaticVoidMethodA 이용

    cooM = (*env)->GetStaticMethodID(env, cls, "coo", "(Ljava/lang/String;Ljava/lang/String;)V");
    if(cooM == 0) {
            printf("Method foo isn't found\n");
    }
    else {
            args = (jvalue*)malloc(sizeof(jvalue)*2);
            args[0].l = (*env)->NewStringUTF(env,"papa");
            args[1].l = (*env)->NewStringUTF(env,"ya");
            (*env)->CallStaticVoidMethodA(env, cls, cooM,args );
    }

 여기서 주의할 것은 CallStaticVoidMethodA의 두 번째 인자는 jobject타입이 아닌, jclass타입이란 것이다. 클래스 메쏘드이니 당연하기도 하다.


상위 클래스의 메쏘드 호출

한 걸음 더 나아가 상위 클래스의 메쏘드도 호출할 수 있다. 여기에 해당되는 메쏘드는 모두 NonVirtual이라는 이름을 포함하고 있는데, c++을 배운 이라면, NonVirtual의 의미를 알고 있을 것이다.

상위 클래스 타입의 jclass 객체 획득

    jclass sClass = (*env)->GetSuperclass(env,cls);

메쏘드 ID : GetMethodID함수 이용

    superFooM = (*env)->GetMethodID(env, sClass, "foo", "(Ljava/lang/String;Ljava/lang/String;)V");
    if(superFooM == 0) {
          printf("Method foo isn't found\n");
    }
    else {
           .....
    }

 메쏘드를 호출: CallNonvirtualVoidMethodA

    args = (jvalue*)malloc(sizeof(jvalue)*2);
    args[0].l = (*env)->NewStringUTF(env,"can");
    args[1].l = (*env)->NewStringUTF(env,"dy");
     (*env)->CallNonvirtualVoidMethodA(env,obj,sClass ,superFooM,args );

멤버 필드 접근

 필드를 접근하는 방법 또한 메쏘드를 접근하는 방법과 크게 다르지 않다. 필드가 Private일지라도 접근할 수 있다. 이 또한 몇 가지 함수에 의존하고 있는데, 그 함수의 형식이 메쏘드를 호출하는 함수와 거의 유사하기 때문이다. 일단 다음의 기호를 잊지 말자.

    Z :  boolean  
    B :  byte
    C :  char
    S :  short
    I  :  int
    J :  long
    F :  float
    D : double

  • 이들의 배열은 이들의 타입 기호 앞에 '['를 붙인다. 즉 int 배열은 [I가 된다.
  • 클래스 타입의 경우, L뒤에 클래스명을 패키지명까지 포함해 나열하면 된다. 즉, String클래스인 경우, Ljava.lang.String이다.

 이제 Hello.java에 몇 가지 필드를 추가해 보자.

    private int intVal;
    private static int iStaticIntVal;
    private String strVal = "Hello";

이를 재컴파일 후, javah를 실행하고, 새로이 생긴 함수의 선언부를 HelloImpl.c로 복사해 이것에 대해 추가적으로 구현해 보기로 하자.

필드를 접근하는 것은 두 단계로 이루어진다.

  • 클래스와 필드의 이름과 타입을 이용해 필드의 ID를 얻어낸다.
  • 필드의 ID와 객체를 이용해 실제 필드의 값을 얻어낸다.

인스턴스 필드 접근

먼저 필드의 ID를 얻어내기 위한 함수는 다음과 같다.

     jfieldID GetFieldID(JNI_Env* env,jclass clazz, const char *name, const char *sig)

그리고, 인스턴스 필드를 접근하는 함수들은 다음과 같다.

1) Read 함수
  • jobject GetObjectField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jboolean GetBooleanField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jbyte GetByteField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jchar GetCharField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jshort GetShortField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jint GetIntField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jlong GetLongField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jfloat GetFloatField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jdouble GetDoubleField(JNI_Env* env,jobject obj, jfieldID fieldID)
2) Write 함수
  • void SetObjectField(JNI_Env* env,jobject obj, jfieldID fieldID, jobject val)
  • void SetBooleanField(JNI_Env* env,jobject obj, jfieldID fieldID, jboolean val)
  • void SetByteField(JNI_Env* env,jobject obj, jfieldID fieldID,jbyte val)
  • void SetCharField(JNI_Env* env,jobject obj, jfieldID fieldID, jchar val)  
  • void SetShortField(JNI_Env* env,jobject obj, jfieldID fieldID,jshort val)
  • void SetIntField(JNI_Env* env,jobject obj, jfieldID fieldID,jint val)
  • void SetLongField(JNI_Env* env,jobject obj, jfieldID fieldID, jlong val)
  • void SetFloatField(JNI_Env* env,jobject obj, jfieldID fieldID, jfloat val)
  • void SetDoubleField(JNI_Env* env,jobject obj, jfieldID fieldID, jdouble val)

클래스 필드 접근

Static 필드를 접근하기 위해 먼저 ID를 얻어내야 한다.

    jfieldID GetStaticFieldID(JNI_Env* env,jclass clazz, const char *name,  const char *sig)

그리고, 필드를 접근하는 함수들은 다음과 같다.

Gettor 함수
  • jobject GetStaticObjectField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jboolean GetStaticBooleanField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jbyte GetStaticByteField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jchar GetStaticCharField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jshort GetStaticShortField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jint GetStaticIntField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jlong GetStaticLongField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jfloat GetStaticFloatField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jdouble GetStaticDoubleField(JNI_Env* env,jclass clazz, jfieldID fieldID)
Settor 함수
  • void SetStaticObjectField(JNI_Env* env,jclass clazz, jfieldID fieldID, jobject value)
  • void SetStaticBooleanField(JNI_Env* env,jclass clazz, jfieldID fieldID, jint value)
  • void SetStaticByteField(JNI_Env* env,jclass clazz, jfieldID fieldID, jbyte value)
  • void SetStaticCharField(JNI_Env* env,jclass clazz, jfieldID fieldID, jchar value)
  • void SetStaticShortField(JNI_Env* env,jclass clazz, jfieldID fieldID, jshort value)
  • void SetStaticIntField(JNI_Env* env,jclass clazz, jfieldID fieldID, jint value)
  • void SetStaticLongField(JNI_Env* env,jclass clazz, jfieldID fieldID, jlong value)
  • void SetStaticFloatField(JNI_Env* env,jclass clazz, jfieldID fieldID, jfloat value)
  • void SetStaticDoubleField(JNI_Env* env,jclass clazz, jfieldID fieldID, jdouble value)

예제

이제 이들을 사용해 Hello 클래스의 필드들을 접근해 보기로 하자. Hello.java에 native메쏘드인 다음을 추가하고 컴파일 후, HelloImpl.c에서, 다음을 중심으로 코딩해 보자.

    public native void testFieldAccess()

정적 변수 접근

정적 필드인 iStaticIntVal 필드를 접근하여, 값을 읽어들인 후, 다시 2를 더해 값을 써 보자.

    jfieldID jFieldId;
    jint iStaticIntVal;
    jclass cls = (*env)->GetObjectClass(env, jobj);

    jFieldId = (*env)->GetStaticFieldID(env,cls,"iStaticIntVal","I");
    if(jFieldId == 0) {
                    printf("Field iStaticIntVal not Found in Hello class\n");
                    return;
    }

    //  값을 읽어들인 후,
    iStaticIntVal = (*env)->GetStaticIntField(env,cls,jFieldId);

    // 2를 더해, 다시 그 값을 쓴다.
    (*env)->SetStaticIntField(env,cls,jFieldId,(iStaticIntVal+2));  

인스턴스 변수 접근

    jint iVal;
    jfieldID jFieldId;
    jclass cls = (*env)->GetObjectClass(env, jobj);
    jFieldId = (*env)->GetFieldID(env,cls,"intVal","I");
    if(jFieldId == 0) {
                    printf("Field intVal not Found in Hello class\n");
                    return;
    }
    iVal = (*env)->GetIntField(env,jobj,jFieldId);
    printf("iVal in C = %d\n",iVal);
    (*env)->SetIntField(env,jobj,jFieldId,iVal);

그런데, 실제로 int를 가지고 실험해 본 결과, C에서 값을 잘 넘겨받는 것까지는 좋은데, 다시 자바로 값을 써 줄 때, 인자가 잘 전달되지 않는 현상을 보였다. 좀더 생각해 볼 문제이다.

스트링 접근

스트링은 객체이므로 객체를 접근하는 방식을 통해 접근해야 한다. 우선 GetFieldID 함수의 인자로 "Ljava/lang/String;"을 주목하면, 객체의 접근 방식과 동일함을 알 수 있다. 여기에서 세미콜론(;)을 빠뜨리면, 인식하지 못하므로 주의하기 바란다.

    jstring jstr;
    jfieldID jFieldId;
    jclass cls = (*env)->GetObjectClass(env, jobj);

    jFieldId = (*env)->GetFieldID(env,cls,"strVal","Ljava/lang/String;");
    if(jFieldId == 0) {
                    printf("Field strVal not Found in Hello class\n");
                    return;
    }

    jstr = (*env)->GetObjectField(env,jobj,jFieldId);
    (*env)->SetStaticIntField(env,cls,jFieldId,(iStaticIntVal+2));  
    str = (*env)->GetStringUTFChars(env, jstr, 0);
    printf("Get String : %s\n",str);

    새로운 스트링을 생성하여, 이것의 레퍼런스값을 str 필드에 할당하려면, 다음과 같이 한다.
    jstr = (*env)->NewStringUTF(env, "123");
    (*env)->SetObjectField(env, jobj, jFieldId, jstr);

기타 객체를 호출하는 방법도 스트링과 거의 동일하다. (*env)->GetObjectField(env,jobj,jFieldId);를 통해, jobject타입의 객체를 얻어낸 후, 필요에 따라 이 객체의 메쏘드를 호출하면 된다.


예외 사항

예외 사항 던지기

이제 예외 사항을 던지는 방법을 알아보자.  예외 사항들은 각각 클래스로 되어 있으므로, 이들의 클래스 정보를 얻어낸 후, 다음의 함수를 이용하면 된다.

     jint ThrowNew(JNI_Env* env, jclass clazz, const char *msg)

Hello.java에서 testFieldAccess가 java.io.IOException을 던지도록 수정해 보자.

    public native void testFieldAccess() throws java.io.IOException;

    javac Hello.java
    javah -jni Hello

 이제 새로이 HelloImpl.c에서, testFieldAccess의 끝에 다음을 추가해 보자.

       jclass eCls;

       eCls = (*env)->FindClass(env, "java/io/IOException");
        if(eCls != 0) {
                (*env)->ThrowNew(env, eCls, "IOException from C");
        }

예외 사항 감지하기

JNI의 C코드에서, 자바의 메쏘드를 호출했을 때.예외 사항이 돌아올 수 있다. 이 때, 감지하는 데 사용되는 함수는 다음과 같다.

    jthrowable ExceptionOccurred(JNIEnv* env)

이것은 jthrowable타입의 예외 사항 객체를 반환해 준다. 그 예외 사항에 정보를 출력하는 데 사용되는 함수도 제공된다.

    void ExceptionDescribe(JNI_Env* env)

그리고, 예외 사항이 처리된 후, 다시 예외 사항이 없는 것처럼 하려면, 다음과 같은 함수를 수행한다.

    void ExceptionClear(JNI_Env* env);

이제 Hello.java에 새로운 메쏘드를 추가해 보자.

    public void returnException() throws java.io.IOException {
            throw new java.io.IOException("IOException from Java");
    }

이 메쏘드를 C에서 호출하면, 예외 사항이 그쪽으로 반환될 것이다. 이것을 처리하는 코드는 다음과 같다.

           jmethodID jmId;
           jthrowable jexcp;

           jmId = (*env)->GetMethodID(env,cls,"returnException","()V");
            if(jmId == 0) {
                    printf("Method returnException not found\n");
            }
            else {
                    (*env)->CallVoidMethod(env,jobj,jmId);
                    jexcp = (*env)->ExceptionOccurred(env);  
                    if(jexcp) {
                            (*env)->ExceptionDescribe(env);   // 예외 사항 정보 출력
                            (*env)->ExceptionClear(env);
                    }
            }

가비지 콜렉션

강제 레퍼런스 해제

원래 네이티브 메쏘드 내의 로컬 변수들이나 전역 변수들이 각각 지니고 있는 자바 객체에 대한 레퍼런스는 네이티브 메쏘드가 끝난 후에야 비로소 없어진다. 따라서, 네이티브 메쏘드가 오랜 시간동안 수행될 경우, 초반에만 실질적으로 사용될 뿐, 후반부에서는 쓰이지 않는 객체의 레퍼런스조차 메쏘드 전체가 수행이 끝날 때까지 남아있게 되는 셈이다. 이때 강제로 레퍼런스를 무효화시킬 수 있는 방법이 있다. 다음의 함수를 사용하면 된다.

  • void DeleteLocalRef(JNI_Env* env,jobject obj)   // 지역 변수
  • void DeleteGlobalRef(JNI_Env* env,jobject gref)  // 전역 변수

동기화

synchronized블록과 같은 동기화 블록을 C 코드내에서 지정해야 할 때가 있다. 바로 쓰레드에 의해 네이티브 메쏘드가 호출되었을 때, 이 메쏘드가 공유 변수들을 접근할 수 있기 때문이다. 그러한 용도로 사용되는 함수는 다음과 같다.

  • (*env)->MonitorEnter(JNI_Env* env,jobject obj);
  • (*env)->MonitorExit(JNI_Env* env, jobject obj);

 이 두 메쏘드 사이에 있는 코드들은 쓰레드들간에 동기화된다.

'old > Basic' 카테고리의 다른 글

Parcelable Object 1  (0) 2010.07.06
안드로이드 기본 개념  (0) 2010.07.06
http://mc500.tistory.com/entry/Goole-Android-Build-해-보  (0) 2010.02.09
how to make sqplite3 table  (0) 2010.02.09
What is Android?  (0) 2010.02.04
Posted by jazzlife
,

abstract와 interface

old/JAVA 2010. 7. 1. 18:42
abstract class : 추상화 정도가 낮고 몸통을 가진 methods를 포함할 수 있다. extends로 단일상속
interface : 추상화 정도가 높고 몸통을 가질 수 없다. implements로 interface class에서 extends 다중상속
Posted by jazzlife
,
Scanner: 입력 소스로부터 문자데이터를 읽어오는데 사용.
ex)
   
Scanner s = new Scanner(System.in);
    String input = s.nextLine();


StringTokenizer: delimiter를 기준으로 token이라는 여러 개의 작은 문자열로 잘라내는 데 사용.
ex)
   StringTokenizer st = new StringTokenizer(expression, "+-*/=()", true);


DecimalFormat: 숫자를 형식화하는 데 사용
ex)
   String number = "1234567.89";  
   DecimalFormat df = new DecimalFormat("#.#E0");
   String result = df.format(number);


SimpleDateFormat: 다양한 날짜 출력
ex)
   SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM--dd");
   ...
   System.out.println(sdf. format(tday));


ChoiceFormat: 특정 범위에 속하는 값을 문자열로 변환
ex)
   double[] limits = { 60, 70, ...};
   String[] grades = {"D, "C"...};

    int[] sores = { 100, 95.....60, 70 };

    ChoiceFormat form = new ChoiceFormat(limits, grades);
...


MessageFormat: 정해진 양식에 맞게 출력하는데 사용
ex)
    String msg = "Name: {0} \nTel: {1} \nAge: {2}.";
    Object[] arguments = {"이자바", "02-123-1234", "27"};

    String result = MessageFormat.format(msg, arguments);
Posted by jazzlife
,
HashMap: HashTable의 신버전, key와 value를 묶어서 하나의 entry로 저장한다.
               key값으로 데이터를 호출한다. 많은 양의 데이터를 검색하는데 뛰어난 성능.
               key값은 유일해야하고 value는 중복을 허용한다.

TreeMap: 이진검색트리 형태로 key와 value가 쌍으로 이루어져있다. 범위검색이나 정렬이 필요한 경우에 사용.

Properties: HashTable을 상속받아 구현한 것. key와 value를 String값으로 받아서 사용하고 파일 입출력의 기능을 사용할 때 주로 사용한다. 시스템 속성을 출력할 때도 사용.

ex) HashMap

class HashMapEx1 {
{
   HashMap map = new HashMap();
   map.put("castello", "1234");
   map.put("asdf", "1111");
   map.put("asdf", "1234);

   Scanner s = new Scanner(System.in);

   while(true) {
      System.out.println("id와 pw입력해주세요");
      System.out.print("id: ");
      String id = s.nextLine().trim();

      System.out.print("password: ");
      String password = s.nextLine().trim();
      System.out.println();

      if(!map.containKey(id)) {
            System.out.println("id가 존재하지 않습니다." + "다시 입력해주세요");
            continue;
       } else {
            if(!(map.get(id)).equals(password)) {
                System.out.println("비번이 일치하지 않습니다. 다시 입력하세요");
           } else {
                  System.out.println("id와 비번이 일치합니다.");
                  break;
           }
      }
  }
}


ex) Properties

class PropertiesEx3
{
   public static void main(String[] args)
   {
      Properties prop = new Properties();
      prop.setProperty("timeout", "30");
      prop.setProperty("language","한글");
      prop.setProperty("size", "10");
      prop.setProperty("capacity", "10");

      try {
            prop.store(new FileOutputStream("output.txt"), "Properties Ex");
            prop.storeToXML(new FileOutputStream("output.xml"), "Properties Ex");
      } catch(IOException e) {
            e.printStackTrace();
       }
   }
}
Posted by jazzlife
,
HashSet : 중복요소 저장 안 하고 저장순서 유지 안 한다.
LinkedHashSet : 중복요소 저장 안 하고 저장순서 유지한다.

TreeSet : 이진검색 트리 형태로 저장하는 컬렉션 클래스
             최대 두개의 자식노드, 왼쪽이 오른쪽보다 값이 작다, 추가/삭제 시간이 걸린다, 검색/정렬에 유리하다.


ex)
class HashSetEx1 {
  public static void main(String[] args) {
    Object[] objArr = { "1", new Integer(1), "2",... }
    Set set = new HashSet();
 
    for(int i=0; i < objArr.length; i++) {
      set.add(objArr[i]);
   }
   System.out.println(set);
  }
}


class LinkedHashSetEx1 {
  public static void main(String[] args) {
    Object[] objArr = { "1", new Integer(1), "2",... }
    Set set = new LinkedHashSet();
 
    for(int i=0; i < objArr.length; i++) {
      set.add(objArr[i]);
   }
   System.out.println(set);
  }
}


TreeSet
ex) Structure
class TreeNode {
   TreeNode left;
   Object element;
   TreeNode right;
}

ex)
class TreeSetEx1
{
   public static void main(String[] args)
   {
      TreeSet set = new TreeSet();
      int[] score = { 80, 90,50...,10, 100};
     
      for(int i=0; i<score.length; i++)
          set.add(new Integer(score[i]));
     
      ..
   }
}

Posted by jazzlife
,

Stack과 Queue

old/JAVA 2010. 5. 24. 17:41
Stack :  LIFO구조 - 수식계산, 괄호검사, undo/redo, 뒤로/앞으로
Queue: FIFO구조 - 최근 사용문서, 인쇄 대기목록, 버퍼

'old > JAVA' 카테고리의 다른 글

Set Interface ( HashSet, TreeSet)  (0) 2010.05.25
컬렉션 저장요소 접근 인터페이스 ( Enumeration, Iterator, ListIterator)  (0) 2010.05.24
LinkedList  (0) 2010.05.24
Vector와 ArrayList  (0) 2010.05.24
Synchronization (ArrayList, HashMap)  (0) 2010.05.24
Posted by jazzlife
,

LinkedList

old/JAVA 2010. 5. 24. 17:39
: 크기를 변경하는데 제약이 있고 중간에 데이터를 삽입/삭제가 힘든 단점을 해결하기 위해 LinkedList를 사용.

ArrayList : 순차적 추가/삭제는 빠르나 중간 추가/삭제는 느리다.
LinkedList : 중간 추가/삭제가 빠르나 데이터가 많을수록 접근성 떨어짐.

구조1]

    class Node {
         Node next;
         Object obj;
   }


구조2]

    class Node {
        Node next;
        Node previous;
        Object obj;
    }

'old > JAVA' 카테고리의 다른 글

컬렉션 저장요소 접근 인터페이스 ( Enumeration, Iterator, ListIterator)  (0) 2010.05.24
Stack과 Queue  (0) 2010.05.24
Vector와 ArrayList  (0) 2010.05.24
Synchronization (ArrayList, HashMap)  (0) 2010.05.24
Collection Framework  (0) 2010.05.24
Posted by jazzlife
,

Vector와 ArrayList

old/JAVA 2010. 5. 24. 17:32
Vector를 개선한 것이 ArrayList.
Vector는 기존 코드를 위해 남겨둔 것이므로 가능한 ArrayList를 사용.

공통점: List 인터페이스 구현, 저장순서 유지/중복 허용, 배열을 사용, 용량 부족시 늘어나긴 하지만 시간 오래걸림
차이점: Vector는 멀티쓰레드에 대하여 동기화가 되어있다.
          
ex)

class ArrayListEx2 {
 public static void  main(String[] args) {
   final int LIMIT = 10;
   String source = "0123456789abcdefghijklmnop";
   int length = source.length();
 
   List list = new ArrayList(length/LIMIT+10);

   for(int i=0; i<length; i+=LIMIT) {
     if(i+LIMIT<length)
           list.add(source.substring(i, i+LIMIT));
     else
           list.add(source.substring(i));
    }

    for(int i=0; i<list.size(); i++) {
        System.out.println(list.get(i));
    }
 }
}

'old > JAVA' 카테고리의 다른 글

Stack과 Queue  (0) 2010.05.24
LinkedList  (0) 2010.05.24
Synchronization (ArrayList, HashMap)  (0) 2010.05.24
Collection Framework  (0) 2010.05.24
garbage collection 이란?  (0) 2010.05.10
Posted by jazzlife
,

Multi-Thread 프로그래밍에서는 데이터의 일관성을 위해서 동기화가 필요하다.
하지만 Thread 프로그래밍이 아닌 곳에서는 불필요하며 성능을 떨어뜨리는 요인이 된다.

ArrayList와 HashMap에서는 동기화를 필요할 때만 동기화 할 수 있도록 되어있다.

[동기화 메서드]

static Collection synchronizedCollection(Collection c)
static List synchronizedList(List list)
static Map synchronizedMap(Map m)
static Set synchronizedSet(Set s)
static SortedMap synchronizedSortedMap(SortedMap m)
static SortedSet synchronizedSortedSet(SortedSet s)


[사용 방법]

List list = Collections.synchronizedList(new ArrayList(....));

'old > JAVA' 카테고리의 다른 글

LinkedList  (0) 2010.05.24
Vector와 ArrayList  (0) 2010.05.24
Collection Framework  (0) 2010.05.24
garbage collection 이란?  (0) 2010.05.10
Iterator(구 Enumeration), ListIterator  (0) 2010.03.16
Posted by jazzlife
,

Collection Framework

old/JAVA 2010. 5. 24. 17:04
Collection Framework : 다수의 데이터를 쉽게 처리할 수 있는 표준화된 방법을 제공하는 클래스들

핵심 인터페이스 : List, Set, Map

1) List
    : 중복을 허용하면서 저장순서는 유지하는 컬렉션 클래스 구현 ( ArrayList, LinkedList, Vector, Stack )

2) Set
   : 중복과 저장순서가 유지되지 않느 컬렉션 클래스 구현 ( HashSet, TreeSet )

3) Map
   : Key와 value르 하나의 쌍으로 묶어서 저장하는 컬렉션 클래스 구현 ( HashTable, HashMap, LinkedHashMap, SortedMap, TreeMap )

   Map.Entry
     : Map 인터페이스 내의 Entry 인터페이스
 
    public interface Map {
    ...
         interface Entry {
                 Object getKey();
                 Object getValue();
                 Object setValue(Object value);
                 blooean equals(Object o);
                 int hashCode();
         }
      {

   
   

'old > JAVA' 카테고리의 다른 글

Vector와 ArrayList  (0) 2010.05.24
Synchronization (ArrayList, HashMap)  (0) 2010.05.24
garbage collection 이란?  (0) 2010.05.10
Iterator(구 Enumeration), ListIterator  (0) 2010.03.16
Stack & Queue  (0) 2010.03.15
Posted by jazzlife
,
1. garbage collection (쓰레기 수집)

- 자바 프로그램이 더 이상 참조되지 않는 메모리를 모아 시스템에 되돌려 주는 것.

- 프로그래머는 메모리에 대해서는 아무 관여하지 않는다.

- 참조중인 객체를 찾는 방법

참조계수 기법 (reference-counting) : 객체를 참조하는 갯수를 추적하여 참조중인 객체를 구분.

- heap 안에 있는 각 객체마다 참조계수(reference-count)가 유지

- 어떤 객체가 처음 생겨서 그 객체를 참조하는 변수에 배정하면 참조계수는 1이고 다른 변수가 그 객체를 참조할 때 참조계수는 1씩 증가한다. 그리고 객체를 참조하는 변수가 다른 값이 배정되면 1씩 감소한다.

- 참조계수가 0인 객체 : garbage

추적 기법 (tracing) : 루트 노드에서 시작하는 참조의 그래프를 추적하는 방법.



① simple garbage collection

mark-sweep 방식

- 주기적으로 전체 메모리를 탐색하여 garbage를 찾음.

- local variable array와 stack에서 참조하는 각 객체를 '유효함' 상태로 체크

- 유효하다고 체크된 각 객체들이 참조하는 다른 객체들도 역시 '유효함'

⇒ mark 단계

- 유효함 체크 과정이 끝나고 유효함 체크를 받지 못한 객체들은 garbage로 간주

- garbage로 간주된 객체는 garbage collector에 의해 수거된다.

⇒ sweep 단계

- garbage collection이 진행중인 경우, garbage collector 이외의 모든 쓰레드는 중지되어야만 한다. garbage collection 하는 중에, 유효하다고 체크되지는 않았지만 실제로는 유효한 객체에 대한 참조를 다른 쓰레드가 메모리에서 옮기고 다닐 수 있기 때문에 그 객체는 garbage로 간주될 수 있기 때문이다.



② generational garbage collection

- 메모리 일부만 탐색하여 garbage를 찾는 방식으로 mark-sweep 방식보다 전체 처리 속도 향상.

- 자바 프로그램에서 만들어지는 대부분의 객체들은 매우 짧은 시간 동안만 참조되어진다는 것과 오랫동안 유효했던 객체는 계속적으로 유효할 것이라는 전제를 바탕으로 한다.

- 객체들은 언제 생성되었는지를 기준으로 세대별로 묶이게 된다.

- heap을 객체들 한 '세대(generation)'에 의해 두 개 이상의 각 subheap으로 나눔.

- 객체가 처음 생성되면 특정 subheap에 메모리를 할당해준다.

- 대부분의 객체가 수명이 짧으므로 첫 번째 garbage collection이 일어나면 살아있는 객체는 아주 적음. 이 때 가장 어린 세대로서 살아 남은 객체는 다음 세대로 등급이 올라감 : 다른 supheap로 옮겨진다.

- 어린(younger) 객체는 늙은(older) 객체보다 더 자주 garbage collection을 함.



※ compaction 기법

- garbage collection 이후 객체들이 참조하는 메모리는 순서대로 되어 있지 않고 흩어져서 존재하기 때문에 큰 크기의 객체가 차지할 만한 곳을 찾기가 힘들어지게 된다.

⇒ fragmentation (단편화)

- 이런 단편화를 최소화하기 위해서 compaction 기법을 사용한다.

- 현재 참조되고 있는 객체를 heap의 한 쪽 끝으로 모으는 기법

- 하나의 메모리 공간이 다른 공간으로 복사되어야 함.

- 옮겨진 객체는 새로운 위치로 참조가 갱신됨.



※ finalization (객체 최종화)

- class는 static으로 선언되지 않고, 아무런 인자도 받지 않고, 어떤 값도 return 하지 않는 finalize라는 method를 사용하여 finalization을 요구할 수 있다.

- 객체가 finalizer를 가지고 있으면서 더 이상 참조되지 않으면 garbage collector는 객체에 의해 점유되고 있는 메모리를 재사용하기 위해 finalizer를 호출한다.

- finalizer는 반드시 한번 호출되어야 한다.

- 객체가 언제 어디서 어떤 순서로 finalizer를 호출한다는 것은 보장하지 않는다.

- protected void finalize() throws Throwable {

super.finalize();

}

'old > JAVA' 카테고리의 다른 글

Synchronization (ArrayList, HashMap)  (0) 2010.05.24
Collection Framework  (0) 2010.05.24
Iterator(구 Enumeration), ListIterator  (0) 2010.03.16
Stack & Queue  (0) 2010.03.15
Deep Copy vs Shallow Copy  (0) 2010.03.15
Posted by jazzlife
,