달력

1

« 2025/1 »

  • 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
  • 29
  • 30
  • 31

출처 : http://rothmans.wordpress.com/category/java


기본적인 코딩 표준

1.클래스명
  : 첫문자는 대문자로 시작하고, 구분되는 부분도 대문자로 시작한다.

2.메소드명
:첫문자는 소문자로 시작하고, 구분은 대문자로 짓는다.메소드명에는 대조할 수 있는
  이름을 붙인다.

3.섀도우 필드는 작성하지 않는다.
  :섀도우 필드, 즉 부모 클래스의 필드명과 동일한 필드명은 버그의 원인이 되므로,
   가능한 한 사용하지 않는다. 언어의 사양에 따라 컴파일러는 통과할 수 있다.

4.외부 리소스는 반드시 해제한다.
  :파일 입출력(I/O)과 데이터베이스의 커넥션,커서는 확실하게 close메소드를 실행하지
   않으면 자원이 해제되지 않는다. 반드시 finally에서 close 메소드를 실행하도록 한다.

ex) Connection = con =null;
     try
     {
     //처리
     }
     finally
     {
      if(con !=null)
      {
        con.close();
      }
     }

5.catch한 예외는 반드시 처리한다.
  :catch한 예외에 대해 아무런 대처도 하지 않으면 디버그를 곤란하게 만든다. 반드시 로그
   출력을 하거나 throw한다. 이유가 있어서 무시하게 될 경우는 무시하는 이유을 주석으로
   붙인다.







Java 성능개선을 위한 Programming 기법

JDK1.3버전 이후로 지원되는 HotSpot VM은 기본적으로 Hip에 동적으로 할당된 Object는 거의 회수할 수 있다고 한다. 하지만 이 기능으로 인해서 VM은 엄청난 OverHead를 가지게 된다. 무리한 Object의 생성은 생성 당시에도 많은 OverHead를 초래하지만, 생성된 Object를 회수하기 위해서는 더 많은 작업이 요구된다. 이를 해결하기 위한 몇 가지 Tip이 있는데, Avoiding Garbage Collection, Object 재사용, static instance variable의 사용에 의한 단일 클래스 인스턴스 구현 방법 등이 그것이다. 핵심은 가능한 Object 생성을 피하자는 것이다.

▶ Avoiding Garbage Collection(static method사용)
예제1)
String string=”55″;
int theInt=new Integer(string).intValue();

예제2)
String string=”55″;
int theInt=Integer.parseInt(string);

예제1)에서는 Integer 클래스를 생성한 다음 string에서 정수값을 추출해 냈다. Object를 생성하고 초기화하는 과정은 상당한 cpu 집약적인 작업이고, Hip 영역에 Object가 생성되고 수집되기 때문에 가비지 컬렉터 작업을 수반한다. 가능한 Object의 Instance가 필요 없는 static 메소드를 사용한다. 예제2) 참조.

▶ Avoiding Garbage Collection(임시 Object 생성 금지)
가장 흔한 예로 String Object의 append를 위해서 (+) 연산을 사용하는 것을 들 수 있다. (+) 연산자를 사용해서 String Object를 append할 경우 우리가 생각하는 것 보다 훨씬 더 많은 임시 Object가 생성되고, 가비지 컬렉터에 의해 다시 수집된다. String Object의 append연산을 위해서는 StringBuffer 클래스를 사용한다. 예제1)과 예제2) 참조

예제1)
String a=”Hello”;
a=a+”World”;
System.out.println(a);

예제2)
StringBuffer a=new StringBuffer();
a.append(”Hello”);
a.append(”World”);
System.out.println(a.toString());

어떤 메소드는 Object의 복사본을 반환하는 경우가 있다. 대표적인 예로 스트링 클래스의 trim() 메소드를 들 수 있다. trim()메소드가 수행되면 기존의 Object는 수집되고, 기존 Object의 복사본이 사용되게 된다. 임시 Object 생성과 복사본을 반환하는 메소드가 루프 안에서 사용될 경우 무수히 많은 Object가 생성되고 수집되기 때문에 심각한 문제를 야기하게 된다. 루프 내부에서 Object를 생성하는 것은 가급적 피해야 한다.

예제3)
for(i=0;i<1000;i++){
Date a=new Date();
:
}

예제4)
Date a;
for(i=0;i<1000;i++){
a=new Date();
:
a=null;
}

예제3)과 예제4)는 현재 날짜와 시간을 얻어오기 위해 루프 안에서 Object를 생성했다. 보통 set으로 시작하는 메소드는 Object의 Instance 값을 재정의 한다. API를 충분히 참조한 다음 지원 메소드가 없을 경우, 클래스를 상속받아 요구에 적합한 메소드를 만드는 방법도 고려할 필요가 있다. 기존 API를 이용한 Object 초기화 방법은 아래 Object 재사용(메소드를 사용한 Object 초기화) 부분 참조.

▶ Avoiding Garbage Collection(primitive data type 사용)
Date 클래스나 String 클래스의 값들중 int나 long 형으로 표현하여 사용할 수 있는 경우가 있다. 예를 들어

String a=”1492″;
String b=”1997″;

과 같을 경우 a와 b는 굳이 String 형으로 표현하지 않아도 된다. 하지만 여기서 주의할 점은 Object의 값을 기본 데이타형으로 Casting 하는 작업이 오히려 시간이 더 많이 걸릴 수도 있는 것이다.
클래스의 인스턴스 변수로 기본 데이타형을 사용하면 Object의 크기도 줄어들고, Object 생성 시간도 줄일 수 있다.

▶ Object 재사용(Pool Management)
Object 재사용 기법으로 흔히 Pool Management 기법을 사용한다. 이는 임의 갯수의 Object를 미리 생성해 두고 이를 Vector 클래스를 사용해서 관리하는 방법이다. 해당 Object를 사용하기 위해서 Pool의 Vector에 있는 Object를 하나 가져오고, 다 사용하고 나면 다시 Pool에 반납한다. 이는 기존에 공개되어 있는 Hans Bergsten의 Connection-Pool의 PoolManager클래스에서 사용되고 있다.(Professional JAVA Server Programming. 정보문화사. 2000.4.4. 제9장 연결풀링 부분 참조) Object Pool을 사용할 경우, 반환되는 Object가 초기화되어 반환되지 않을 경우 다음에 Pool에서 Object를 가져와서 사용하게 되면 문제를 야기할 수 있기 때문에 초기 클래스 Design시 꼼꼼하게 따져 봐야 한다.

▶ Object 재사용(메소드를 사용한 Object 초기화)
예제1)
StringBuffer sb=new StringBuffer();
sb.append(”Hello”);
out.println(sb.toString());
sb=null;
sb=new StringBuffer();
sb.append(”World”);
out.println(sb.toString());

예제1)과 같이 사용할 경우 하나의 인스턴스 변수를 사용하기는 하지만, 두 번의 초기화 과정을 거치게 된다.

예제2)
StringBuffer sb=new StringBuffer();
sb.append(”Hello”);
out.println(sb.toString());
sb.setLength(0);
sb.append(”World”);
out.println(sb.toString());

위와 같이 각 클래스에서 지원해 주는 메소드를 사용하여 Object를 재사용 할 수 있다.

▶ static instance variable의 사용에 의한 단일 클래스 인스턴스 구현
다음은 Hans Bergsten의 PoolManager 클래스 코드 중 일부다.

public class PoolManager{
static private PoolManager instance;
:
private PoolManager(){
init();
}
static synchronized public PoolManager getInstance(){
if (instance == null){
instance = new PoolManager();
}
:
return instance;
}
private void init(){
:
}

PoolManager형의 인스턴스가 static으로 선언되어 있다. getInstance() 메소드는 현재 생성되어 있는 PoolManager의 Object를 조사하고 만약 Object가 있으면 Object를 반환하고 없으면 생성자를 호출해서 PoolManager의 Object를 생성한 후 반환한다. 결국 JVM 내부에는 하나의 PoolManager Object가 존재하게 된다. 단일 클래스 인스턴스 기법을 사용할 경우 하나의 인스턴스를 사용하기 때문에 해당 인스턴스의 무결성 부분이 문제가 된다. 이를 위해 다양한 Synchronization 기법을 사용하게 된다. 아래 I/O 퍼포먼스 개선 부분 참조.

▶ clone() 메소드 사용으로 Object 생성에 따른 OverHead를 피함

private static int[] data = new int[2][2];
int[] someMethod(){
int[] a = (int[])this.data.clone();
return a;
}

대부분의 클래스들에는 clone() 메소드가 존재한다. clone() 메소드가 호출되면 Object의 복사본을 반환하는데, 대신 클래스의 생성자를 호출하지 않기 때문에 생성자 호출에 의한 OverHead를 피할 수 있다. clone() 메소드를 사용할 때의 trade-off 문제는 다음에 예제를 참조 할 것.

static int[] Ref_array1={1,2,3,4,5,6,7,8,9};
static int[][] Ref_array2={{1,2},{3,4},{5,6},{7,8}};

int[] array1={1,2,3,4,5,6,7,8,9}; //faster than cloning
int[] array1=(int[])Ref_array1.clone(); //slower than initializing

int[][] array2={{1,2},{3,4},{5,6},{7,8}}; //slower than cloning
int[][] array2=(int[][])Ref_array2.clone(); //faster than initializing

▶ Method Inline에 의한 method호출 감소
예제1)
public class InlineMe{
int counter=0;
public void method1(){
for(int i=0;i<1000;i++){
addCount();
System.out.println(”counter=”+counter);
}
public int addCount(){
counter=counter+1;
return counter;
}
public static void main(String args[]){
InlineMe im=new InlineMe();
im.method1();
}
}

예제1)에서 addCount() 메소드를 다음과 같이 수정하면

public void addCount(){
counter=counter+1;
}

위와 같이 수정할 경우 addCount() 메소드는 컴파일시 Inline 되어서 실제 메소드를 호출하지 않고 같은 결과를 반환한다. 즉 method1()이 실제 수행될 때는 다음과 같이 수행.

public void method1(){
for(int i=0;i<1000;i++){
counter=counter+1;
System.out.println(”counter=”+counter);
}

▶ 생성자 설계
예제1,2,3) 모두 같은 역할을 하는 생성자들로 구성되어 있다. 하지만 퍼포먼스 측면에서 보면 예제3)이 가장 효율적이다. 하지만 클래스를 설계 할 때 예제1)과 같이 해야 할 때도 있다. 클래스가 요구하는 조건에 따라 생성자의 설계방법이 다르겠지만, Object를 생성할 때 가능한 생성자를 적게 호출하는 방법을 사용하는 것이 퍼포먼스 면에서 좋다는 것은 당연한 일이다.

예제1)
예제2)
예제3)
class SlowFlow{
private int someX, someY;
SlowFlow(){
this(777);
}
SlowFlow(int x){
this(x,778);
}
SlowFlow(int x, int y)
someX=x;
someY=y;
}
}
class SlowFlow{
private int someX, someY;
SlowFlow(){
this(777,778);
}
SlowFlow(int x){
this(x,778);
}
SlowFlow(int x, int y)
someX=x;
someY=y;
}
}
class SlowFlow{
private int someX, someY;
SlowFlow(){
someX=777;
someY=778;
}
SlowFlow(int x){
someX=x;
someY=778;
}
SlowFlow(int x, int y)
someX=x;
someY=y;
}
}

▶ “extends” VS “implements”
예제1) extends
import java.awt.event.*;
import java.awt.*;
public class MyWindowAdapter extends WindowAdapter{
public void windowClosing(WindowEvent we){
Container source=(Container)we.getSource();
source.setVisible(false);
}
}

예제2) implements
import java.awt.event.*;
import java.awt.*;
public class MyWindowListener implements WindowListener{
public void windowClosing(WindowEvent we){
Container sourve=(Container)we.getSource();
source.setVisible(false);
}
public void windowClosed(WindowEvent we){}
pubic void windowActivated(WindowEvent we){}
public void windowDeactivated(WindowEvent we){}
public void windowIconified(WindowEvent we){}
public void windowDeiconified(WindowEvent we){}
public void windowOpened(WindowEvent we){}

“implements”의 경우에는 특정 메소드를 구현하고 인터페이스에 정의된 모든 메소드를 코딩해야 하기 때문에 코드의 낭비를 초래하는 반면, “extends”의 경우에는 슈퍼 클래스에 정의된 메소드들 중 필요한 메소드만 overriding 하면 된다. ==> 설계 시 추상클래스를 사용할 것인지 인터페이스를 사용할 것인지 고려.

▶ 클래스 집약
예제1)
public class Person{
private Name name;
private Address address;
}
class Name{
private String firstName;
private String lastName;
private String[] otherNames;
}
class Address{
private int houseNumber;
private String houseName;
private String streetName;
private String town;
private String area;
private String greaterArea;
private String country;
private String postCode;
}

예제1)에서 정의된 Person 클래스는 Name형의 name과 Address형의 address, 두 개의 인스턴스 변수를 가진다. 클래스를 설계할 때 가능한 클래스의 수를 줄여서 수행 시 동적으로 생성되는 Object의 수를 줄일 수도 있다. 예제1)에서 정의된 세 개의 클래스는 하나의 클래스로 집약될 수 있다.

예제2)
public class Person{
private String firstName;
private String lastName;
private String[] otherNames;
private int houseNumber;
private String houseName;
private String streetName;
private String town;
private String area;
private String greaterArea;
private String country;
private String postCode;
}

▶ I/O 퍼포먼스 개선
자바에서는 자료를 읽거나 쓰기 위해 stream을 사용한다. 자바는 두가지 형태의 stream을 지원한다. Readers and Writers와 Input and Output stream이 그것이다. Reader and Writers는 high-level의 I/O(예. String)를 지원하고 Input and Output stream은 low-level의 I/O(byte)를 지원한다. 속도 향상을 위해서는 Buffered stream을 사용한다. Buffered stream을 사용할 경우 버퍼의 기본값은 2K이다. 이 값은 조정될 수 있으나, 자료의 용량이 클 경우 메모리가 많이 필요하기 때문에 Buffered stream을 사용할 경우 여러 가지 사항을 고려해야 한다.

예제1) Simple file copy
public static void copy(String from, String to) throws IOException{
InputStream in=null;
OutputStream out=null;
try{
in=new FileInputStream(from);
out=new FileOutputStream(to);
while(true){
int data=in.read();
if(data==-1)
break;
out.write(data);
}
in.close();
out.close();
}finally{
if(in!=null){in.close();}
if(out!=null){out.close();}
}
}

Buffered stream을 사용하지 않고 I/O를 했을 경우의 예제이다. 370K의 JPEG 파일을 복사하는데 10800ms.

예제2) Faster file copy
public static void copy(String from, String to) throws IOException{
InputStream in=null;
OutputStream out=null;
try{
in=new BufferedInputStream(new FileInputStream(from));
out=new BufferedOutputStream(new FileOutputStream(to));
while(true){
int data=in.read();
if(data==-1)
break;
out.write(data);
}
}finally{
if(in!=null){in.close();}
if(out!=null){out.close();}
}
}

Bufferd stream을 사용해서 퍼포먼스를 개선한 예제이다. 예제1)과 같은 파일을 복사하는데 130ms.

예제3) Custom buffered copy
public static void copy(String from, String to) throws IOException{
InputStream in=null;
OutputStream out=null;
try{
in=new FileInputStream(from);
out=new FileOutputStream(to);
int length=in.available();
byte[] bytes=new byte[length];
in.read(bytes);
out.write(bytes);
}finally{
if(in!=null){in.close();}
if(out!=null){out.close();}
}
}

while루프를 사용하지 않고 배열을 사용함으로서 퍼포먼스를 개선한 예제이다. 예제1)과 같은 파일을 복사하는데 33ms. 하지만 예제3)은 byte배열로 선언되는 메모리 버퍼의 크기가 실제 파일의 크기와 동일해야 한다. 이에 따라 두 가지의 문제점이 발생할 수 있다. 첫 번째는 파일의 용량이 클 경우 상당한 메모리 낭비를 초래한다는 점이다. 두 번째 문제점은 copy()메소드가 수행될 때마다 new byte[]에 의해 버퍼가 새로 만들어진다는 점이다. 만일 파일의 용량이 클 경우 버퍼가 만들어지고 Garbage Collector에 의해 수집될 때 상당한 OverHead를 초래할 수 있다.

예제4) Improved custom buffered copy
static final int BUFF_SIZE=100000;
static fianl byte[] buffer=new byte[BUFF_SIZE];
public static void copy(String from, String to) throws IOException{
InputStream in=null;
OutputStream out=null;
try{
in=new FileInputStream(from);
out=new FileOutputStream(to);
while(true){
synchronized(buffer){
int amountRead=in.read(buffer);
if(amountRead==-1)
break;
out.write(buffer,0,amountRead);
}
}finally{
if(in!=null){in.close();}
if(out!=null){out.close();}
}
}

크기가 100K인 byte 배열을 임시버퍼로 지정하고, 이를 static으로 선언함으로서 퍼포먼스를 개선했다. 예제1)과 같은 파일을 복사하는데 22ms. static buffer의 사용으로 I/O작업을 수행할 경우 발생할 수 있는 문제점을 해결하기 위해 synchronized block을 사용했다. 비록 synchronization을 사용함에 따라 성능 저하를 초래하지만, 실제 while 루프에 머무는 시간이 극히 짧기 때문에 퍼포먼스에 문제는 없다. 테스트에 의하면 synchronized 버전과 unsynchronized 버전 모두 같은 시간에 수행을 완료했다.

▶ 웹 환경에서 Caching을 이용한 자바 퍼포먼스 개선
웹 환경에서 Object caching 기법은 주로 DB나 파일에서 동일한 내용을 가져오는 루틴에서 사용된다. DBMS에 sql문을 던지고 결과를 받아오는 부분의 내용이 거의 변동이 없을 경우 요청 시마다 매번 sql문을 실행시켜서 결과를 받아오는 것이 아니라 최초 실행된 값을 그대로 반환하는 기법이다. 그리고 시간 Check 기법을 이용해서 특정 시간 경과 후 요청이 들어오면 이전 요청에 의해 수행되어진 값을 갱신해서 반환한다. 결과에 의한 반환값이 메모리에 부담이 되지 않을 정도로 크지 않은 경우, 실시간으로 변경된 정보를 반환값으로 사용하는 루틴이 아닐 경우 유용하게 사용될 수 있다.

▶ Performance CheckList
. 임시로 사용하기 위해 Object를 생성하는 것을 피하라. 특히 Loop에서..
. 빈번하게 호출되는 메소드에서 Object를 생성하는 것을 피하라.
. 가능한 Object를 재사용 하라.
. 임시 Object의 생성을 줄이기 위해 데이타 타입 컨버전 메소드를 재정의 하는 방법을 고 려하라.
. 메소드 설계 시 데이타를 유지하고 있는 Object를 반환하는 메소드보다 데이타로 채워진 재사용 가능한 Object에 접근하는 메소드를 정의하라.
. string이나 Object를 integer 로 대치하라. Object 비교를 위해 equal() 메소드를 호출하지 말고 기본 데이타 타입의 == 연산자를 사용하라.
. 인스턴스 변수로 기본 데이타 타입을 사용하라.
. 단지 메소드 호출을 위해 Object를 생성하는 것을 피하라.
. String 연속 연산자 (+)를 사용하는 것보다 StringBuffer 클래스를 사용하라.
. 복사본을 생성하는 메소드 보다 Object를 직접 수정하는 메소드를 사용하라.
. 생성자는 간단하게… 상속 계층은 얕게…
. 인스턴스 변수를 초기화 하는 것은 한 번 이상 하지 말 것.
. 생성자 호출을 피하기 위해 clone() 메소들 사용할 것.
. 간단한 배열일 경우에는 초기화를.. 복잡한 배열일 경우에는 clone() 메소드 호출.
. 프로그램 내부에서 Object 생성 시기를 조절해서 Object 생성에 따른 bottlenecks를 없앤 다.
. 어플리케이션 내부에서 여분의 시간이 허용된다면 가능한 Object를 빨리 생성하라. 생성 된 Object를 내부적으로 유지하고 있다가 요청이 발생하면 할당하라.
. 사용 가능성이 희박하거나, 분산처리에 의해 Object를 생성할 경우 Object는 생성 시기를 늦춰라.

:
Posted by 라면스프
2008. 10. 28. 17:37

[JSP] JSP 자주쓰는 코드 정리 Enjoy/JSP2008. 10. 28. 17:37


출처 : http://blog.naver.com/korekiss/20044092634


<%
response.sendRedirect("링크주소"); // 주소로 이동
str.length(); //글자길이 갯수 구하기
str.substring(3,7); //글자의 3에서 7번째까지 추출
str.append("문자열"); //str의 문자열에 추가

▷JSP 액션태그

 <jsp:forward>       다른페이지로 이동
 <jsp:include>       다른페이지를 페이지 안에 추가                                               <jsp:include page="url" flush="true" />
 <jsp:parma>         forward, include, plugin과 같이 사용되어 인자를 추가할때
 <jsp:plugin>         애플릿과 같이 클라이언트에서 사용되는 객체 삽입
 <jsp:useBean>     자바빈즈 사용
 <jsp:setProperty>  자바빈즈 프로피티의 값을 설정할때
 <jsp:getProperty>  자바빈즈 프로피티의 값을 얻는데 사용

 

▷토큰자르기 (java.util.*)
 String tel = "055-1234-5678";
 StringTokenizer str = new StringTokenizer(tel, "-");
 str.nextToken()  //055
 str.nextToken()  //1234
 str.nextToken()  //5678

 

▷파일 (java.io.*)
 -파일생성
 String filename = "c:\\aaaaa\\bbbbb\\test.txt";  //리눅스일때 http://mediafile.paran.com/MEDIA_11888685/BLOG/200711/1195526717_
 File f = new File(filename);  //파일클래스 작성
 f.createNewFile();  //파일 생성

 -파일쓰기
FileWriter fw = new FileWriter(filename);  //객체생성
 String data = "ㅇㅇㅇㅇㅇㅇㅇ";
 fw.write(data);  //파일쓰기
 fw.close();  //파일저장

-파일읽기
 FileReader fr = new FileReader(filename);  //리더객체생성
 BufferedReader br = new BufferedReader(fr);  //버퍼리더객체생성 - readLine();
 String line;
 while((line=br.readLine()) != null){
    out.println(line + "<br>");  //여러줄 읽어오기
 }

 -파일정보보기
 f.getAbsolutePath();  //절대경로
 f.getName();  //파일이름
 f.getParent(); //파일위치한 경로
 f.length();  //파일크기

 -파일삭제
 if(f.exists()){  //파일이 존재하면
    f.delete();
    out.println("파일이 삭제되었습니다.");
 }else{
    out.println("파일이 없습니다.");
 }

 

▷형변환
 String -> int
 String a="15";
 int b = Integer.parseInt(a);

 
 int -> String
 int a=12;
 Integer  b=new Integer(a);  //Integer객체 선언
 String c = B.toString();  //toString() 형변환
 

▷세션
 if(session.getAttribute("sid")==null){  //세션값이 아무것도 없을때
   out.println("세션 정보가 없습니다.");
   session.setAttribute("sid", session.getId());  //임의의 세션id를 sid에 저장
   session.setAttribute("name", "이름");  //이름을 name세션에 저장
 }else{
   out.println("이브라우저에 대한 세션 ID는 " + session.getAttribute("sid")+ "입니다.");
   out.println("name에 저장된 값은 " + session.getAttribute("name") + "입니다.");
 }
 session.setMaxInactiveInterval(3600);  //세션 유지시간 (1시간동안)

▷쿠키
 -저장
 Cookie cook1 = new Cookie("name", "aaa");  //쿠키객체생성
 cook1.setPath="/";  //쿠키가 적용될 웹서버의 url 경로
 cook1.setMaxAge(60*60*24*365); //쿠키가 유지되는 시간(1년) -1일경우 삭제하지 않는한 영구
 response.addCookie(cook1);  //쿠키를 클라이언트에 세팅

 Cookie cook2 = new Cookie("mail", aaa@aaa.com);
 cook2.setPath="/";
 cook2.setMaxAge(60*60*24*356);
 response.addCookie(cook2);


 -가져오기
 try(
  Cookie[] cookies = request.getCookies();
   for(int i = 0; i < cookies.length; i++){
     out.println(cookies[i].getName() + "은" + cookies[i].getValue() + "입니다.
   }
 }catch (Exception e){
   out.println(e);
 }

 -삭제하기
 try{
   Cookie[] cookies = request.getCookies();
   for(int i=0; i< cookies.length; i++){
     Cookie cook = cookies[i];
     cook.setMaxAge(0);
     response.addCookie(cook);
   }
   out.println("쿠키가 삭제되었습니다.");
 }catch(Exception e){
   out.println(e);
 }

 

▷JDBC드라이브
 Class.forName("org.gjt.mm.mysql.Driver");
 -mysql
 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "test", "pass");  //연결객체생성
 Statement stmt = conn.createStatement();  //스테이트먼트 객체생성
 ResultSet rs = stmt.executeUpdate("insert into test(id, age) values('aaa','123')");  //쿼리문실행
 rs.next();  //다음 리절트 셋

:
Posted by 라면스프
2008. 10. 28. 17:34

[JAVA] Shell Script 팁 (Unix포함) Enjoy/JAVA2008. 10. 28. 17:34


출처 : http://blog.naver.com/vital45/110024999490


1. 스크립트를 생성할때 구조화를 염두에 둔다
- Unix에서 보통 파일 구조가
/bin
/var/log
등등의 형식을 따르고 있기 때문에 가독성을 높이고 직관적으로 알아볼수 있게 하기 위해 생성

2. find  $PATH -type f | grep -v ".svn"
- .svn이 포함된 디렉토리는 무시하고 file을 검색

3. find . -name "*.sh" | xargs grep "STRING"
- *.sh 의 파일 중 내용에 STRING이 포함되어 있는 곳을 stdout으로 출력

4. 제어권을 갖고 있는 곳은 한군데로 통일하고, 나머지 스크립트는 모든 인자를 받아서
각각의 행동을 하도록 한다.

5. 로그 이름은 script이름과 되도록 통일하여 가독성을 높이도록 한다.

6. wget --output-file=/DIRECTORY/output.log --spider http://localhost:8080/
- wget: 지정된 경로에서 파일 다운로드
- --output-file : 로그 메세지를 지정된 파일에 저장
- --spider: 파일 다운로드 받지 않음

7. shell에서 덧셈 시
- loopcount=0
- loopcount=`expr $loopcount + 1`
- 중요한건 expr 문장을 감싼것은 `(tild)라는 것. 물론 syntax에서 구별할수 있겠지만...

8. svn checkout REPO_PATH PATH
- checkout 명령은 PATH에 없으면 REPO_PATH에서 내려받고, 이미 PATH가 존재하면 update를 한다.
- checkout, update 명령을 굳이 구별할 필요가 없음.

9. shell 스크립트 호출 후 표준출력을 웹 화면에서 보여주는 방법 (jdk 1.5)
(1) jsp 에서
cmd = "ssh";
url = id@server;
args = "A B C";

ProcessBuilder process = ProcessBuilder.start(cmd, url, args);
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

while ((line = br.readLine()) != null)
   System.out.println(line);

(2) java에서
cmd = "ssh";
url = id@server;
args = "A B C";

ProcessBuilder process = ProcessBuilder.start(cmd, url, args);
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

while ((line = br.readLine()) != null) {
   // newLine 가공 부분은 따로 처리하는게 있는걸로 알고있는데..
  // 나중에 한번 찾아봐야 할듯. 아래는 예상 코드
   String contents = line + "\n";
}

contents를 jstl을 이용하여 뿌려주는 식으로...

10. Subversion에서의 tag
- SVN Repository를 구성할때 아래와 같은 구조를 권장하고 있다.
repository/trunk : 현재 작업본
repository/branches : 테스트 버전이랄까? (beta버전)
repository/tags : 잠금 버전 (완성본)

TotoiseSVN에서 branches/tags를 클릭하면 실제로 수행하는 명령어는 svn copy다.
svn copy는 Working Copy(이하 WC) 와 Repository PATH(이하 URL)에서 실행할 수 있다. (조합 4가지)
svn copy -m "Message" [WC|URL] [WC|URL]

참고: svn switch 를 실행하면 현재 경로에서부터는 svn repository path를 변경한다.
.svn/entries 의 주소를 확인해보면 알 수 있다.
더 확장하면 svn propset을 이용한 external link를 하는 법도 있는데.. 이건 정확히 잘 모르겠음.

11. argument를 delimeter로 잘라서 loop 돌리는 법
INPUT=$1
DELIM=":" # Delimiter

for part in `echo $input | sed "s/$DELIM/ /g"`
do
   echo $part
done
- sed명령어를 묶어준 것도 역시 `(tild) 이다.

12. ls 에 대한 새삼 깨달은 팁
- ls | grep $option1 | grep $option2
grep 을 줘서 각 인자에 대한 리스트를 뽑아올 수 있다.

 

:
Posted by 라면스프
2008. 10. 28. 17:13

[JSP] HttpSessionBindingListener Enjoy/JSP2008. 10. 28. 17:13


출처 : http://blog.naver.com/korekiss/20038228350


HttpSessionBindingListener 는 웹에서 동시 사용자의 수 또는 하나의 아이디로 동시접속을 제한 할때 유용한 인터페이스 이다.  HttpSessionBindingListener 는 두개의 메소드를 지니는데 valueBound() 와 valueUnbound() 메소드 이다.
 
valueBound() 는 HttpSessionBindingListener 클래스의 인스턴스가 세션에 attribute로
등록될떄 호출된다  session.setAttribute(플래그, 값)
valueUnbound()는 session.removeAttribute(플래그); 사용시
또는 세션종료시  session.invalidate()호출된다.
 
다음은 이를 이용한 동시 사용자및 중복 로그인 방지 프로그램이다.
 
 
LoginManager.java
 
package cookie;
 
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.util.Hashtable;
import java.util.Enumeration;
 
public class LoginManager implements HttpSessionBindingListener
{
             private static LoginManager loginManager = null;
             private static Hashtable loginUsers = new Hashtable();
             private LoginManager(){
                           super();
             }
             public static synchronized LoginManager getInstance(){
                           if(loginManager == null){
                                        loginManager = new LoginManager();
                           }
                           return loginManager;
             }
 
             //아이디가 맞는지 체크
             public boolean isValid(String userID, String userPW){
                           return true;   //자세한 로직은 미구현
             }
 
             //해당 세션에 이미 로그인 되있는지 체크
             public boolean isLogin(String sessionID){
                           boolean isLogin = false;
                           Enumeration e = loginUsers.keys();
                           String key = "";
                           while(e.hasMoreElements()){
                                        key = (String)e.nextElement();
                                        if(sessionID.equals(key)){
                                                     isLogin = true;
                                        }
                           }
                           return isLogin;
             }
 
             //중복 로그인 막기 위해 아이디 사용중인지 체크
             public boolean isUsing(String userID){
                           boolean isUsing = false;
                           Enumeration e = loginUsers.keys();
                           String key = "";
                           while(e.hasMoreElements()){
                                        key = (String)e.nextElement();
                                        if(userID.equals(loginUsers.get(key))){
                                                     isUsing = true;
                                        }
                           }
                           return isUsing;
             }
 
             //세션 생성
             public void setSession(HttpSession session, String userID){
                           loginUsers.put(session.getId(), userID);
                           session.setAttribute("login", this.getInstance());
             }
 
             //세션 성립될 때
             public void valueBound(HttpSessionBindingEvent event){
             }
 
             //세션 끊길때
             public void valueUnbound(HttpSessionBindingEvent event){
                           loginUsers.remove(event.getSession().getId());
             }
 
             //세션 ID로 로긴된 ID 구분
             public String getUserID(String sessionID){
                           return (String)loginUsers.get(sessionID);
             }
 
             //현재 접속자수
             public int getUserCount(){
                           return loginUsers.size();
             }
};
 
Bind_login.jsp
 
<%@ page contentType="text/html;charset=euc-kr"
             import="cookie.LoginManager"%>
 
<% LoginManager loginManager = LoginManager.getInstance(); %>
<html>
<body>
<center>
현재 접속자수 : <%= loginManager.getUserCount() %><p>
<hr>
<%
             if(loginManager.isLogin(session.getId())){  //세션 아이디가 로그인 중이면
                           out.println(loginManager.getUserID(session.getId())+"님 안녕하세요<br>"
                                                                  +"<a href=bind_logout.jsp>로그아웃</a>");
             }
             else{  //그렇지 않으면 로그인 할 수 있도록
%>
<form name="login" action="bind_login_ok.jsp">
아이디: <input type="text" name="userID"><br>
비밀번회: <input type="text" name="userPW"><br>
<input type="submit" value="로그인">
</form>
<%         }%>
</center>
</body>
</html>
 
Bind_login_ok.jsp
 
<%@ page contentType="text/html;charset=euc-kr"
             import="cookie.LoginManager"%>
 
<% LoginManager loginManager = LoginManager.getInstance(); %>
<%
             request.setCharacterEncoding("euc-kr");
            
             String userID = request.getParameter("userID");
             String userPW = request.getParameter("userPW");
 
             if(loginManager.isValid(userID, userPW)){
                           if(!loginManager.isUsing(userID)){
                                        loginManager.setSession(session, userID);
                                        response.sendRedirect("bind_login.jsp");
                           }
                           else{
                                        throw new Exception("이미 로그인중");
                           }
             }
             else{
                           throw new Exception("ID/PW 이상");
             }
%>
 
Bind_logout.jsp
 
<%@ page contentType="text/html;charset=euc-kr"%>
<%
             session.invalidate();
             response.sendRedirect("bind_login.jsp");
%>
 
:
Posted by 라면스프
2008. 10. 27. 14:43

Java Tips Enjoy/JAVA2008. 10. 27. 14:43


출처 : http://www.nsftools.com/tips/JavaTips.htm#searchfiles


Java Tips

Using Wildcard Expressions in Java
Getting a File from a Web Site or FTP Site
Java FTP Class
Java Server Addin for Domino
HttpEcho Program
Java HTTP Proxy
Java MessageBoxes, InputBoxes, and ProgressBars
XML NodeReader Class
Java Sample Code Database
Transform WSDL Servlet
Undocumented Base64 Java Classes
Using Java Reflection to Get Class Information
Multi-Part MIME Message Parser
Java RichTextOutputStream Class
Accessing the System Clipboard with Java
Searching for Text in Files
Manipulating JPEG Images
Testing ReplaceSubstring Routines
Terminating Threads and Reacting to Shutdown in Java
Open JAR Files Natively In Windows


Using Wildcard Expressions in Java
August 31, 2002 (updated September 11, 2002)

Here's a Java class that I wrote to evaluate basic wildcard expressions (using *, ?, or []) in Java strings. If you're using the JDK/J2SE 1.4 or higher, you should probably use the java.util.regex package to make Regular Expressions to provide string pattern-matching functionality, because it will give you a much greater range of functionality. There are (at the time of this writing) some good examples of Regular Expression usage here on the Sun website. However, sometimes we Notes developers are stuck using older versions of the JDK...

I also included a sample class called "jdir.java" that calls the PatternMatch class and uses it in a FilenameFilter, as an example. It simulates the very basic functionality of the "dir" command in DOS (make sure you enclose those wildcard arguments in quotes!).

PatternMatch.java
jdir.java

My good friend Mark (a fantastic Java programmer) also told me about an open source regular expression library at apache.org that will work with JDK versions prior to 1.4. That one should be much more full-featured than the one I wrote. Thanks Mark!


Getting a File from a Web Site or FTP Site
August 31, 2002

This is a Java class I wrote to get a file (or a web page) from a web site or an anonymous ftp site. It has additional functionality to allow you to do this kind of thing through a proxy server, which makes it a little more useful in an office setting.

InternetFile.java


Java FTP Class
August 31, 2002 (updated September 11, 2002)

This information has been expanded and moved to a separate page:
see JavaFtp.htm


Java Server Addin for Domino
October 14, 2002 (updated May 17, 2003)

Here's an example of how to write an R5 Domino Server Addin using Java (which is normally something you'd do in C or C++). I got the idea from this tip on the SearchDomino site. The example I wrote doesn't do much, but it should give you a good framework for writing your own Addins. I tried to be as liberal as possible with my comments.

Keep in mind that using the the lotus.notes.addins.JavaServerAddin class from Notes.jar is totally unsupported functionality (at least in R5), so you are using it at your own risk. Normal caveats apply. This also means that I had to make some educated guesses about some of the functionality that I describe in the source code, so please send me a note if you find any mistakes.

JavaAddinTest.java
JavaAddinTest.class


HttpEcho Program
November 21, 2002

This is a simple Java program that takes incoming HTTP requests on a given port and returns them right back to the sender of the request. It's useful for looking at the HTTP headers sent by your browser, or seeing the structure of SOAP requests that are being sent to a server. For example, just compile the Java file into a class file and run "java HttpEcho 8080", and then point your browser to "http://localhost:8080/whatever" to see your browser headers.

Actually, I wrote two slightly different versions of the program: HttpEcho.java, which is single-threaded, and HttpEchoMT.java, which is multi-threaded. That's just to give you an example of how to do some simple multi-threading on a program like this.

HttpEcho.java
HttpEchoMT.java


Java HTTP Proxy
December 18, 2002 (updated February 1, 2003)

This is a multi-threaded HTTP proxy server implementation in Java. Ideally you'll just run it on your local workstation so you can watch HTTP requests going back and forth (because of the way the threading works in this code, I wouldn't recommend running it as a proxy server that serves multiple clients -- see the comments in the code for more detail).

You can either point this proxy to a direct network/Internet connection, or you can point it to another proxy server (if that's how you're set up). Even though the jProxy class has a 'main' method that allows you to run it all by itself, I also tried to structure the methods in the class so you can easily call it from other classes. I didn't spend the time to javadoc any of the comments, but the code should be commented well enough that you can understand what's going on by reading through it. (Updated on Feb 1 so that the HTTP header elements are separated by \r\n instead of just \n, to comply with the official HTTP spec).

jProxy.java


Java MessageBoxes, InputBoxes, and ProgressBars
December 23, 2002 (updated January 15, 2002)

Here's a classic case of a simple little piece of functionality that ended up taking lines and lines of code to implement. All I wanted to do was add a MessageBox and an InputBox to a Java agent that would run in the Notes client, and I wanted to use the java.awt classes so I wouldn't have to package the javax.swing classes along with the agent (note that Swing was included with Lotus Notes starting with release 6, but I was stuck with R5 at the time). It wouldn't have been too bad, except for the fact that java.awt doesn't have a native way of displaying multiple lines of text in a Label-type component...

Since it wasn't quite as straightforward as I thought it would be, I packaged up some sample code, added comments to the source, and posted it for you here. It's a MessageBox class that allows you to present simple Ok/Cancel dialogs, input boxes, drop-down lists, and multiple selection lists. Also included as a special bonus is a MultiLineLabel class that you can use to create text labels of a fixed width that have multiple lines (with text wrapping, too!).

Of course, just because this is implemented as a Lotus Notes agent doesn't mean that you can't use it in your other Java applets/applications. If you do any kind of Java UI work without the Swing classes, this code will probably come in handy.

MsgBox.java

Update: Here's a similar piece of code that allows you to implement a non-modal Progress Bar in a Java agent. Like the MessageBox example above, the ProgressBar class uses only the java.awt classes, so you don't have to package anything special with your agents that use it.

ProgBar.java


XML NodeReader Class
January 17, 2003 (updated February 27, 2003)

The NodeReader class provides some basic functionality for stepping through the elements of a w3c XML Node, so you don't have to write your own loops around a NodeList. It's similar to the TreeWalker class that ships with many org.w3c.dom compatible packages, but the XML4j.jar package that ships with Lotus Notes/Domino doesn't have a TreeWalker class, so I wrote this.

This has been tested with the JDK 1.1.8 and 1.3.1, both in an R5 Notes agent and in a stand-alone Java application. It's also got JavaDoc comments, so you can produce some basic documentation (although I did include a code sample with the comments, so that should help you along).

NodeReader.java


Transform WSDL Servlet
February 19, 2003

I was playing around with WSDL files last week, and I ran across this article about transforming a WSDL file using XSLT. As I was reading it, I thought it would be interesting to write a servlet that would apply the XSL file in the article to any given WSDL file on the web. So I wrote one, and you can download it below.

It worked on my R5 Domino servers using the Domino Servlet Manager, and the method in the code that actually performs the XSL transformation could also be easily copied and pasted into a Notes agent (note that it may not work properly if your server is sitting behind a proxy server). If nothing else, this might be a good framework for how to write a simple servlet.

There's also some interesting information about transforming WSDL files using XSL on the CapeScience site.

TransformWSDL.java


Undocumented Base64 Java Classes
February 23, 2003

While I was poking around through my Java jar file, I discovered a couple of undocumented (i.e. not in the JavaDocs) classes in Sun's Java distribution called sun.misc.BASE64Encoder and sun.misc.BASE64Decoder. As expected, they Base64 encode and decode data, and they even have really convenient methods for encoding/decoding an InputStream to an OutputStream, which is handy for working with files (I used reflection to figure out what the public methods were).

As always, you should be a little cautious working with undocumented features, but I'd bet these are pretty safe (Base64 ain't rocket science). It could save you a little coding or the need to import extra classes into your project, and I even tested the functionality with an R5 Notes client, so I'd guess these classes have been around for a while (at least since the 1.1.8 JDK).

Here's some sample code that demonstrates example usage:

Base64Test.java


Using Java Reflection to Get Class Information
February 24, 2003

This is a simple example of how to use Java reflection to get information about a compiled Java class. This is useful for getting the public fields, constructors, and methods of a class that you may not have documentation for.

ReflectClass.java


Multi-Part MIME Message Parser
March 4, 2003

This is a class that will read and parse an RFC 1521 multi-part MIME message. It works with any InputStream, it's been tested with the 1.1.8 and 1.3.1 JDK, and it doesn't require any additional classes or overhead.

The code is pretty well commented (JavaDoc comments and everything), including a class usage example, so you should be able to figure out how to use it fairly quickly.

SimpleMimeReader.java


Accessing the System Clipboard with Java
May 6, 2003

This is a wrapper to the java.awt.datatransfer.Clipboard methods that allow you to copy and paste items to the system clipboard. Strings are handled natively, and other Object types can be used with a little programming of your own. The big reason to use this class is because it sets the java.awt process up in a daemon thread, which allows your program to terminate properly without a call to System.exit() -- see the JavaDoc comments in the code for more explanation.

ClipHelper.java


Searching for Text in Files
May 30, 2003

A while ago, I did some testing to find out how to search for a String in a file as quickly as possible. This may seem like a fairly rudimentary thing to do, but I was quite surprised at how much variance there was in the speed of many of the obvious solutions, especially when you started looking at large or multiple files. You can use different InputStreams and Readers, adopt different buffering strategies, and so on.

In the end, I found that it seemed to be faster to read a FileInputStream in chunks of 2048 bytes at a time, and compare a byte array representation of my String with the bytes of the file. Just for fun, I wrapped the file searching function (which is called searchFile) in a little Swing application that's pretty easy to use. There are also examples of how to perform some handy little tasks in Swing in there too (like responding to double-clicks and launching threads with your ActionListeners), so some of the other code might be useful to you as well.

(If you're lucky enough to be using Java 1.4 or higher, there's a nice example of how to grep a file using regular expressions and the new java.nio classes in the Sun api docs.)

SearchFiles.java


Manipulating JPEG Images
July 30, 2003

Here's a class I was playing around with that manipulates JPEG images. It's the JpgImage class, and it allows you to do things like rotate, scale, and invert a JPEG image. You can either read an image in from a file or pass a BufferedImage to the constructor. The Sun version of Java 1.2 or higher is required, as this class not only uses some Graphics2d classes, but also a few of the com.sun.image.codec.jpeg classes.

A lot of the methods are trivial wrappers around some of the transform classes, but the rotate() method was a little tricky. See the source code for details.

As an example, I also wrote the JpgResizer class, which is really just a command-line application that calls the methods in the JpgImage class, based on the command-line parameters that you pass. Again, see the source code for details.

JpgImage.java
JpgResizer.java


Testing ReplaceSubstring Routines
September 17, 2003 (updated March 14, 2003)

This is just a little speed test of a few different routines that can be used to replace all occurrences of a substring within a larger String. More interesting than the functions themselves (StringBuffer was faster...no surprise there) is the testing method. Reflection is used to run all the validation and the speed testing, which makes it very modular.

Normally, for tests of multiple similar functions like this, you end up copying and pasting a lot of redundant code to run the same test against multiple functions. Using the techniques in this example, you can see how Java reflection makes it possible to simply pass the name of the method you want to test, and all the testing code ends up in a single routine that gets called multiple times.

(Added the ReplaceSubstring6 method on March 14, 2004, which is similar to the other methods but checks for a condition where both the original string and the find string are "", in which case the method should return the replace string, not the original string as with the other methods. Thanks to John Marshall for that tip.)

ReplaceSubstringTest.java
ReplaceSubstringTest.class


Terminating Threads and Reacting to Shutdown in Java
November 10, 2003

When you're writing a multi-threaded program in Java, you generally want to add some handling for killing the threads when the program is ready to terminate, especially if your threads are running continuously (or potentially for a very long time) while waiting for an event to occur. For instance, a multi-threaded command-line Java program might be structured similar to this example:

ThreadKillTest.java

This type of setup should allow our program to kill and cleanup the thread and its resources, as long as the program shuts down the way we're expecting it to. However, what if a user decided to just use Control-C to terminate the program instead? None of the structured clean-up work would get done, and you could be left with a mess. This could happen just as easily with a GUI program if someone kills it at the command-line, despite the fact that you've registered your handlers for java.awt (addWindowListener) or javax.swing (setDefaultCloseOperation) or whatever GUI library you're using.

Luckily, starting with Java 1.3, Sun gave us the ability to register shutdown hooks to handle just such a case. All you have to do is make a call to

    Runtime.getRuntime().addShutdownHook(Thread t)

and you're on your way. Here are some good articles to get you started:

http://developer.java.sun.com/developer/TechTips/2000/tt0711.html
http://www.onjava.com/pub/a/onjava/2003/03/26/shutdownhook.html

Once you've got a feel for how addShutdownHook() works, you might want to delve a little deeper with these related articles:

How to effectively handle long-running tasks in Java:
http://builder.com.com/5100-6370_14-1049564-1.html

Writing your own signal handlers in Java (very technical, very cool):
http://www-106.ibm.com/developerworks/ibm/library/i-signalhandling/


Open JAR Files Natively In Windows
October 14, 2004

In case you didn't know, a Java Archive (.jar) file is really just a .zip file with a different extension. Windows 2000 and XP (and I think even ME, if anyone still uses that) came with built-in support for zip files, and you can take advantage of that to open jar files natively in Windows as though they were zip files.

This is convenient not only because you can easily open and navigate the .jar files as though they were folders, but also because Windows will then be able to search within these archive files when you're performing a regular file system search. Very handy for finding .class files buried deep within a .jar.

Technically, the steps to follow are these:

  • open regedit
  • navigate to HKEY_CLASSES_ROOT\.zip
  • right-click the .zip branch and export it to a .reg file
  • edit the .reg file in Notepad
  • do a search and replace to change HKEY_CLASSES_ROOT\.zip to HKEY_CLASSES_ROOT\.jar
  • save and close the .reg file
  • double-click the .reg file to import it to your registry
  • reboot

However, if you don't want to follow all those steps you can probably just download this .reg file and run it locally on your machine:

OpenJars.reg

Make sure you reboot after you've run/imported the .reg file, because the changes won't take effect until you restart the machine. Also, you can easily modify the .reg file to register .ear and .war files as zip files too, if you're so inclined. Those also use the zip technique for compression (well, they've got a certain directory structure too, but they're still just zips).



:
Posted by 라면스프
2008. 10. 24. 18:42

JDBC로 인한 서버 Hang(정지) - weblogic Enjoy/etc2008. 10. 24. 18:42

출처:http://kr.bea.com/support/customer_support/service_pattern/pattern/JDBC_Causes_Server_Hang_Pattern.html


문제 설명
응용 프로그램 또는 WebLogic Server 자체에 사용되는 JDBC 커넥션에 의해 해당 커넥션을 통한 호출이 완료될 때까지 WebLogic Server Execute 스레드가 차단됩니다. JVM은 CPU가 자체적인 스레드 스케줄 메커니즘에 따라 실행 가능한 스레드에 할당되며 SQL 쿼리를 차단하는 스레드가 대기해야 하는지 확인합니다. 그러나 JDBC가 사용 중인 스레드는 SQL 쿼리에서 호출이 반환될 때까지 응용 프로그램용으로 할당됩니다.

트랜잭션 시간이 초과되더라도 해당 트랜잭션에 참가한 리소스가 수행하는 작업이 중단되거나 종료되지 않습니다. 작업은 진행되는 동안 중단 없이 실행됩니다. 트랜잭션 제한 시간에 따라 설정된 플래그에 의해 트랜잭션이 롤백만 가능한 것으로 표시되기 때문에 이 트랜잭션에 대한 이후의 모든 커밋 요청은 TimedOutException 또는 RollbackException이 발생하여 실패합니다. 그러나 위에서 언급한 것처럼 실행 시간이 긴 JDBC 호출로 인해 WebLogic Server Execute 스레드가 차단될 수 있으며 그 결과 모든 스레드가 차단되어 들어오는 요청을 처리할 Execute 스레드가 남지 않으면 인스턴스가 Hang(정지) 상태가 될 수 있습니다.

최신 버전의 WebLogic Server에서는 스레드가 특정 시간(디폴트값: 600초) 내에 반응하지 않는지 규칙적으로 확인하는 상태 검사 기능이 제공됩니다. 이러한 문제가 발생하면 로그 파일에 다음과 같은 오류 메시지가 출력됩니다.

####<Nov 6, 2004 1:42:30 PM EST> <Warning> <WebLogicServer> <mydomain> <myserver> <CoreHealthMonitor> <kernel identity> <>
<000337> <ExecuteThread: '64' for queue: 'default' has been busy for "740" seconds working on the request "Scheduled Trigger",
which is more than the configured time (StuckThreadMaxTime) of "600" seconds.>


이 오류 메시지는 단순히 관리자에게 상태를 알리기 위한 것으로 스레드가 중단되지는 않습니다. 멈춘 스레드는 요청 처리가 완료되어야 다시 실행됩니다. 이 경우 WebLogic Server의 로그 파일에 다음과 같은 메시지가 표시됩니다.

####<Nov 7, 2004 4:17:34 PM EST> <Info> <WebLogicServer><mydomain> <myserver> <ExecuteThread: '66' for queue: 'default'>
<kernel identity> <> <000339> <ExecuteThread: '66' for queue: 'default' has become "unstuck".>


상태 검사 기능의 간격은 변경할 수 있습니다. config.xml 파일의 <Server> 태그에서 StuckThreadMaxTime 속성을 확인하십시오. 자세한 내용은 http://e-docs.bea.com/wls/docs81/config_xml/Server.html#StuckThreadMaxTime 또는 http://e-docs.bea.com/wls/docs81/perform/WLSTuning.html#stuckthread의 WebLogic Server 관리 콘솔 도움말에서 "멈춘 스레드 검색" 단원을 참조하십시오.

페이지 맨 위

문제 해결
다른 프로그래밍 방법이나 JDBC 커넥션 풀 구성을 사용할 경우 JDBC 데드락(Deaklock) 또는 WebLogic Server 인스턴스 Hang(정지) 상태를 초래하는 JDBC 호출이 발생할 수 있습니다. WebLogic Server 인스턴스 Hang(정지) 상태를 해결하고 분석하는 방법에 대한 자세한 내용은 일반적인 서버 Hang(정지) 패턴을 참조하십시오.

이 패턴에서는 서버 Hang(정지) 상태의 원인이 되는 JDBC 호출과 기타 WebLogic Server 인스턴스 Hang(정지) 상태를 초래하는 일반적인 JDBC 관련 문제에 대해 설명합니다. 이 패턴의 참조 지원 패턴은 WebLogic Server 지원 패턴 사이트에서 확인할 수 있습니다.

항목 바로가기

문제 발생 원인
다음과 같은 경우 WebLogic Server 인스턴스 Hang(정지) 상태가 발생할 수 있습니다.
  • JDBC 코드에 DriverManager.getConnection()을 사용하는 경우
  • 데이터베이스에 대한 SQL 쿼리 결과가 반환되는 데 너무 오래 걸리는 경우
  • JDBC 커넥션 풀이 구성된 데이터베이스가 Hang(정지)되어 적절한 시간 내에 호출에 응답하지 않는 경우
  • 느리거나 오버헤드가 발생한 네트워크로 인해 데이터베이스 호출이 느려지거나 Hang(정지)되는 경우
  • 데드락으로 인해 모든 Execute 스레드가 Hang(정지)되어 계속 대기하는 경우
  • JDBC 커넥션 풀의 RefreshMinutes 또는 TestFrequencySeconds 속성으로 인해 WebLogic Server에서 Hang(정지) 기간이 발생하는 경우
  • JDBC 커넥션 풀 축소 및 데이터베이스 커넥션 재생성으로 인해 응답 시간이 길어지는 경우
페이지 맨 위

동기화된 DriverManager.getConnection()
이전의 JDBC 응용 프로그램 코드에서는 특정 드라이버를 사용하는 데이터베이스 커넥션을 검색하기 위해 DriverManager.getConnection() 호출을 사용하기도 했습니다. 이 방법은 데드락을 발생시키거나 커넥션 요청의 성능을 상대적으로 저하시킬 수 있으므로 사용하지 않는 것이 좋습니다. 이러한 문제가 발생하는 원인은 모든 DriverManager 호출이 클래스별로 동기화되어 있어 한 스레드의 특정 DriverManager 호출이 WebLogic Server 인스턴스의 스레드에서 발생하는 다른 모든 DriverManager 호출을 차단하기 때문입니다.

또한 SQLException 생성자에 의해 DriverManager 호출을 발생시키는 대부분의 드라이버에는 로깅을 위한 DriverManager.println() 호출이 포함되어 있기 때문에 DriverManager 호출을 보내는 다른 모든 스레드가 차단될 수 있습니다.

DriverManager.getConnection()에 의해 데이터베이스에 대해 만들어진 커넥션이 반환될 때까지는 상당히 오래 걸립니다. 데드락이 발생하지 않더라도 한 스레드가 커넥션을 가져올 때까지 다른 모든 호출은 대기해야 합니다. WebLogic Server와 같은 멀티 스레드 시스템의 경우 이러한 방법은 바람직하지 않습니다.

이 정보는 http://forums.bea.com/bea//thread.jspa?forumID=2022&threadID=200063365&messageID=202311284&start=-1#202311284에서 발췌한 내용입니다.
DriverManager.getConnection()을 사용해서는 안 된다는 점은 http://e-docs.bea.com/wls/docs81/faq/jdbc.html#501044의 설명서에도 명확히 기술되어 있습니다.

JDBC 코드에 JDBC 커넥션을 사용하려면 WebLogic Server JDBC 커넥션 풀을 사용하고 풀에 대한 DataSource를 정의하여 DataSource에서 커넥션을 가져와야 합니다. 그러면 데이터베이스가 다운되는 등의 문제가 발생한 경우에 리소스 공유, 커넥션 재사용, 커넥션 새로 고침과 같은 풀의 이점을 활용할 수 있습니다. 또한 DriverManager 호출 시에 데드락 발생을 방지할 수 있습니다. WebLogic Server에서 JDBC 커넥션 풀, DataSource 및 기타 JDBC 개체를 사용하는 방법에 대한 자세한 내용은 http://e-docs.bea.com/wls/docs81/jdbc/intro.html#1036718http://e-docs.bea.com/wls/docs81/jdbc/programming.html#1054307을 참조하십시오.

DriverManager.getConnection() 호출에서 차단된 스레드의 일반적인 유형은 다음과 같습니다.
"ExecuteThread-39" daemon prio=5 tid=0x401660 nid=0x33 waiting for monitor entry [0xd247f000..0xd247fc68]
  at java.sql.DriverManager.getConnection(DriverManager.java:188)
  at com.bla.updateDataInDatabase(MyClass.java:296)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:865)
  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:120)
  at weblogic.servlet.internal.ServletContextImpl.invokeServlet(ServletContextImpl.java:945)
  at weblogic.servlet.internal.ServletContextImpl.invokeServlet(ServletContextImpl.java:909)
  at weblogic.servlet.internal.ServletContextManager.invokeServlet(ServletContextManager.java:269)
  at weblogic.socket.MuxableSocketHTTP.invokeServlet(MuxableSocketHTTP.java:392)
  at weblogic.socket.MuxableSocketHTTP.execute(MuxableSocketHTTP.java:274)
  at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:130)



페이지 맨 위

장시간 실행되는 SQL 쿼리
장시간 실행되는 SQL 쿼리는 호출하는 응용 프로그램에 결과를 반환할 때까지 Execute 스레드를 점유합니다. 따라서 응용 프로그램 로드에 의해 요청된 호출을 동시에 여러 개 처리할 수 있도록 WebLogic Server 인스턴스를 구성해야 합니다. 이 경우 제한 요인은 JDBC 커넥션 풀의 Execute 스레드 및 커넥션 수입니다. 또한 가장 중요한 일반 규칙은 리소스 사용량을 최적화하기 위해서는 풀의 커넥션 수를 Execute 스레드 수와 동일하게 설정해야 한다는 것입니다. JTS를 사용하는 경우 실제로 활성화되지 않은 트랜잭션에 대해 커넥션이 확보될 수 있으므로 풀에 커넥션 수를 좀 더 많이 설정해야 합니다.

장시간 실행되는 SQL 호출에서 Hang(정지)되는 스레드의 경우 스레드 덤프에 Hang(정지) 상태의 데이터베이스와 매우 유사한 스택이 표시됩니다. 자세한 내용은 다음 단원에서 비교해 보십시오.

Hang(정지) 상태의 데이터베이스
데이터베이스를 사용하는 응용 프로그램의 성능은 해당 데이터베이스의 성능에 의해 가장 크게 좌우됩니다. 따라서 Hang(정지) 상태의 데이터베이스는 WebLogic Server 인스턴스의 Execute 스레드 중 대부분 또는 일부를 차단시킬 수 있으며 결과적으로 서버 Hang(정지) 상태를 발생시킵니다. 이러한 문제를 진단하려면 Hang(정지) 상태의 WebLogic Server 인스턴스에서 5개 내지 10개의 스레드 덤프를 통해 Execute 스레드가 현재 SQL 호출에 참가하고 있는지, 그리고 데이터베이스의 결과를 기다리고 있는지 확인해야 합니다. 다음은 현재 SQL 쿼리를 보낸 스레드에 대한 스택 트레이스의 일반적인 예입니다.

"ExecuteThread: '4' for queue: 'weblogic.kernel.Default'" daemon prio=5 tid=0x8e93c8 nid=0x19 runnable [e137f000..e13819bc]
  at java.net.SocketInputStream.socketRead0(Native Method)
  at java.net.SocketInputStream.read(SocketInputStream.java:129)
  at oracle.net.ns.Packet.receive(Unknown Source)
  at oracle.net.ns.DataPacket.receive(Unknown Source)
  at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
  at oracle.net.ns.NetInputStream.read(Unknown Source)
  at oracle.net.ns.NetInputStream.read(Unknown Source)
  at oracle.net.ns.NetInputStream.read(Unknown Source)
  at oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:931)
  at oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:893)
  at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:375)
  at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1983)
  at oracle.jdbc.ttc7.TTC7Protocol.fetch(TTC7Protocol.java:1250)
  - locked <e8c68f00> (a oracle.jdbc.ttc7.TTC7Protocol)
  at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2529)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2857)
  at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:608)
  - locked <e5cc44d0> (a oracle.jdbc.driver.OraclePreparedStatement)
  - locked <e8c544c8> (a oracle.jdbc.driver.OracleConnection)
  at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:536)
  - locked <e5cc44d0> (a oracle.jdbc.driver.OraclePreparedStatement)
  - locked <e8c544c8> (a oracle.jdbc.driver.OracleConnection)
  at weblogic.jdbc.wrapper.PreparedStatement.executeQuery(PreparedStatement.java:80)
  at myPackage.query.getAnalysis(MyClass.java:94)
  at jsp_servlet._jsp._jspService(__jspService.java:242)
  at weblogic.servlet.jsp.JspBase.service(JspBase.java:33)
  at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:971)
  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:402)
  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:305)
  at weblogic.servlet.internal.RequestDispatcherImpl.include(RequestDispatcherImpl.java:607)
  at weblogic.servlet.internal.RequestDispatcherImpl.include(RequestDispatcherImpl.java:400)
  at weblogic.servlet.jsp.PageContextImpl.include(PageContextImpl.java:154)
  at jsp_servlet._jsp.__mf1924jq._jspService(__mf1924jq.java:563)
  at weblogic.servlet.jsp.JspBase.service(JspBase.java:33)
  at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:971)
  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:402)
  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:305)
  at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6350)
  at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:317)
  at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:118)
  at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3635)
  at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2585)
  at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:197)
  at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:170)


스레드는 실행 상태가 됩니다. 여러 스레드 덤프의 스레드를 비교하여 SQL 호출로부터 적절한 시간 내에 응답을 받는지 아니면 동일한 호출에서 장시간 Hang(정지)되어 있는지 확인해야 합니다. 스레드 덤프에서 SQL 호출 응답 시간이 너무 긴 것으로 확인되면 해당 데이터베이스 로그를 통해 이러한 성능 저하나 Hang(정지) 상태가 데이터베이스 문제 때문에 발생한 것인지 확인해야 합니다.

페이지 맨 위

느린 네트워크
WebLogic Server와 데이터베이스 간의 통신이 이루어지고 적절한 시간 내에 요청이 처리되기 위해서는 네트워크가 정상적으로 작동하고 안정적이어야 합니다. 따라서 네트워크가 느리면 SQL 쿼리의 결과를 기다리는 Execute 스레드가 Hang(정지)되거나 차단될 수 있습니다. 관련 스택 트레이스는 Hang(정지) 상태의 데이터베이스 단원의 예제와 비슷합니다. WebLogic Server 스레드 덤프만 분석해서는 SQL 쿼리가 Hang(정지)되거나 느려지는 근본 원인을 알 수 없습니다. 스레드 덤프는 SQL 호출의 성능에 문제가 있음을 파악할 수 있는 초기 징후라 할 수 있습니다. 다음 단계로 SQL 호출 성능 저하의 원인이 데이터베이스 문제인지 아니면 네트워크 문제인지를 확인해야 합니다.

데드락
데이터베이스 수준의 데드락과 응용 프로그램 수준의 데드락은 스레드를 Hang(정지) 상태로 만들 수 있습니다. 응용 프로그램 수준 데드락이 있는지 알아보려면 스레드 덤프를 확인해야 합니다. 이 작업을 수행하는 방법은 ServerHang - 응용 프로그램 데드락(Deadlock) 패턴을 참조하십시오. 데이터베이스 데드락은 데이터베이스 로그 또는 WebLogic Server 로그 파일의 SQL Exception을 통해 확인할 수 있습니다. 다음은 관련 SQL Exception의 예입니다.

java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource
  at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:170)
  at oracle.jdbc.oci8.OCIDBAccess.check_error(OCIDBAccess.java:1614)
  at oracle.jdbc.oci8.OCIDBAccess.executeFetch(OCIDBAccess.java:1225)
  at oracle.jdbc.oci8.OCIDBAccess.parseExecuteFetch(OCIDBAccess.java:1338)
  at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:1722)
  at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1647)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2167)
  at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:404)


일반적으로 데이터베이스에서 데드락이 감지되고 원인이 된 하나 이상의 트랜잭션을 롤백하여 데드락을 해결하기까지는 다소 시간이 걸리기 때문에 롤백이 끝날 때까지 하나 이상의 Execute 스레드가 차단될 수 있습니다.

RefreshMinutes 또는 TestFrequencySeconds
데이터베이스 성능 저하, SQL 호출 속도 저하 또는 최다 커넥션이 주기적으로 반복되는 경우 JDBC 커넥션 풀에 설정된 RefreshMinutes 또는 TestFrequencySeconds 구성 속성이 원인일 수 있습니다. 자세한 내용은 JDBC 문제 조사 패턴을 참조하십시오. WebLogic Server 인스턴스와 데이터베이스 사이에 방화벽이 없는 경우 외에는 이 기능을 사용하지 말아야 합니다.

풀 축소
새로운 커넥션 요청은 데이터베이스, 운영 체제 커널 및 WebLogic Server에 상당한 리소스 오버헤드를 발생시키므로 데이터베이스에 대한 커넥션을 한 번 열면 가능한 한 오랫동안 유지해야 합니다. 따라서 이러한 오버헤드를 최소한으로 유지하려면 운영 시스템에서 풀 축소를 사용하지 말아야 합니다. 풀 축소를 사용하면 유휴 풀 커넥션이 닫히게 되고 풀에서 커넥션 요청을 처리할 수 없는 경우에 다시 열립니다.

이와 같은 작업에는 다소 시간이 걸릴 수 있으므로 관련 응용 프로그램 요청에 시간이 예상 외로 많이 걸려 사용자가 시스템이 Hang(정지)되었다고 판단할 수 있습니다. JDBC 커넥션 풀 구성을 최적화하는 방법에 대한 자세한 내용은 JDBC 문제 조사 패턴을 참조하십시오.

페이지 맨 위

Hang(정지) 상태의 WebLogic Server 인스턴스 분석
Hang(정지) 상태의 WebLogic Server 인스턴스를 분석하는 방법에 대한 자세한 내용은 일반적인 서버 Hang(정지) 패턴을 참조하십시오.

시스템이 Hang(정지)되는 경우 대개 문제를 파악하려면 먼저 Hang(정지) 상태의 시스템에서 스레드 덤프를 확인하는 것이 좋습니다. 예를 들어 여러 스레드가 어떤 작업을 수행하고 있는지, 왜 Hang(정지)되었는지 등을 확인합니다. 일반적으로 스레드 덤프는 운영 시스템에서 생성할 수 있지만 오래된 JVM 버전(1.3.1_09 이전 버전)의 경우 스레드 덤프를 생성하는 동안 크래시가 발생할 수 있으므로 주의해야 합니다. 또한 WebLogic Server 인스턴스에 막대한 수의 스레드가 있는 경우 스레드 덤프를 완료하는 데 상당한 시간이 소요되고 그 동안 나머지 스레드가 잠기게 됩니다.

지연 시간이 몇 초 이내인 스레드 덤프를 두 개 이상(5-10개) 생성하십시오. 그러면 다른 스레드의 진행 상태를 확인할 수 있습니다. 또한 시스템이 실제로 Hang(정지)되어 작업이 전혀 진행되지 않거나 처리가 느려 시스템이 Hang(정지)된 것처럼 보이는 경우 이러한 내용이 표시됩니다.

스레드 덤프를 생성하는 방법에 대한 자세한 내용은 "일반적인 서버 Hang(정지)" 지원 패턴 또는 http://e-docs.bea.com/wls/docs81/cluster/trouble.html의 설명서를 참조하십시오.

또한 전체 WebLogic Server 인스턴스가 Hang(정지)된 것인지 아니면 응용 프로그램이 Hang(정지)된 것인지를 확인하십시오. 스레드 덤프를 분석하면 앞의 문제 발생 원인 단원에서 설명한 여러 가지 원인 중에서 인스턴스 Hang(정지)의 실질적인 원인을 알아낼 수 있습니다. 예를 들어 모든 스레드가 getConnection()과 같은 DriverManager 메쏘드에 있는 경우 근본 원인을 파악한 다음에 DriverManager.getConnection() 대신 DataSource 또는 Driver.connect()를 사용하도록 응용 프로그램을 변경해야 합니다.

Samurai라는 유용한 도구를 사용하여 스레드 덤프를 분석하고 여러 스레드 덤프 간에 스레드 진행 상태를 모니터할 수 있습니다. Samurai는 dev2dev 웹 사이트 http://dev2dev.bea.com/resourcelibrary/utilitiestools/adminmgmt.jsp에서 다운로드할 수 있습니다.

또한 dev2dev 웹 사이트 http://dev2dev.bea.com/products/wlplatform81/articles/thread_dumps.jsp에 있는 스레드 덤프 분석에 관한 백서를 통해 스레드 덤프와 서버 Hang(정지)에 대해 자세히 알아볼 수 있습니다.

페이지 맨 위

JDBC 코드 및 JDBC 커넥션 풀 구성 최적화를 위한 팁과 유용한 정보
JDBC 코드 개발 또는 JDBC 커넥션 풀 구성 시에 일반적인 문제 발생을 방지하고 리소스 사용량을 최적화하여 서버 인스턴스 Hang(정지)이 발생하지 않도록 하는 데 도움이 되는 몇 가지 모범 사례를 적용할 수 있습니다.

JDBC 프로그래밍
WebLogic Server에서 리소스 사용량을 최적화하고 데이터베이스 리소스를 절약하려면 응용 프로그램의 JDBC 호출에 JDBC 커넥션 풀을 사용해야 합니다. 응용 프로그램 코드에서 만들어지고 제거되는 커넥션은 불필요한 오버헤드를 발생시킵니다. JDBC 프로그래밍에 대한 자세한 내용은 http://e-docs.bea.com/wls/docs81/jdbc/rmidriver.html#1028977을 참조하십시오. 또한 JDBC 성능 조정에 대한 자세한 내용은 http://e-docs.bea.com/wls/docs81/jdbc/performance.html#1027791을 참조하십시오.

JDBC 코드 및 JDBC 리소스 사용량을 최적화하는 데 유용한 포괄적인 JDBC 관련 정보는 dev2dev Java Database Connectivity 페이지(http://dev2dev.bea.com/technologies/jdbc/index.jsp)를 참조하십시오.

JDBC 커넥션 풀 구성
JDBC 문제 조사 패턴에는 운영 환경의 커넥션 풀 구성에 대한 권장 사항이 나와 있습니다. Hang(정지)이나 성능 저하를 방지하려면 이러한 구성 팁을 고려해야 합니다.

페이지 맨 위

알려진 문제
사용하고 있는 WLS 버전의 릴리스 정보를 주기적으로 검토하여 서비스 팩에서 알려진 문제나 해결된 문제를 확인하고 JDBC 서버 Hang(정지) 관련 문제를 검색할 수 있습니다. 간편하게 다음을 참조하십시오.
드라이버가 현재 실행 중인 명령문이 반환될 때까지 기다려야 하기 때문에 특정 JDBC 커넥션에 대해 트랜잭션 롤백 호출이 바로 처리되지 않는 CR134921 오류는 WLS 8.1 SP3에서 해결되었습니다.

검색하면 릴리스 정보뿐 아니라 추가 도움말에서 언급된 기타 지원 솔루션 및 CR 관련 정보도 알 수 있습니다. 계약 고객은 http://support.bea.com/에 로그인한 다음 Browse 포틀릿에서 Solutions 및 Bug Central을 검색하여 제품 버전별로 사용 가능한 최신 CR을 찾을 수 있습니다.
:
Posted by 라면스프
2008. 10. 24. 18:35

WAS 시스템 설정 기준을 제시하라 Enjoy/etc2008. 10. 24. 18:35

출처 : http://www.imaso.co.kr/?doc=bbs/gnuboard_pdf.php&bo_table=article&page=3&wr_id=913&publishdate=20030401

이상훈 | sanghoone@lgcns.com
J2EE Working Group의 간사로 활동하고 있으며, KM 활동의 일환으로 사내 K-Village SUN 전문가 포럼의 아키텍처 스터디에서 돌쇠(?) 역할을 하고 있다. 개인적으로는 프로덕트 라인 엔지니어링과 스쿠버 다이빙, 인라인 스케이팅, 스노우 보드에 관심이 많다.

다음은 K회사 WAS 관리자와 PM과의 대화내용이다.

WAS 관리자 : WAS 설정 값을 좀 변경하는 게 좋을 것 같습니다.
PM : 왜?
WAS 관리자 : 일부를 좀 바꿔보았더니 성능이 좋아지는 것 같아서요.
PM : 벤더가 왔을 때도 그냥 디폴트(Default)로 설정하라고 했잖아. 설정 바꾸지 말고 디폴트로 설정해! 문제 생기면 책임질꺼야?
WAS 관리자 : @.@

앞의 WAS 관리자와 PM의 대화가 비현실적이었으면 하지만 누구나 경험할 수 있는 안타까운 현실이다. 지난해 J2EE Working Group(이하 J2EE-WG)의 고민도 바로 ‘J2EE 기반의 WAS (Web Application Server) 설정에 대한 불명확성’이었으며, 이를 해결하고자 한 해를 보냈다.
J2EE의 주요 기술이 은행, 이동통신사업 등과 같이 대규모의 시스템에 적용되기 위해서는 시스템 성능에 대한 안정성이 필요하다. 그러나 성능 안정화 및 성능 향상을 위한 튜닝은 실제 프로젝트 팀보다 WAS 벤더에 의존적으로 수행되고 있는 경우가 많고, 개인적인 경험을 토대로 행해지기 때문에 개인의 능력에 따라 성능이 좌우되는 문제점이 제기되고 있다. 이에 J2EE-WG은 성능 안정화를 위한 시스템 성능 향상에 영향을 줄 수 있는 요소들을 선정하고, 각 요소에 대한 국내 J2EE 기반 WAS 벤더의 권고사항을 기초로 하여 성능 향상을 위한 고려사항들을 정리했다.
시스템 성능 향상을 위해서는 업무 모델링, 데이터 모델링, 네트워크, 하드웨어 등 각종 인프라스트럭처, 애플리케이션 아키텍처 등 모든 기본 요소가 업무 특성에 따라 종합적으로 고려되어야 하지만, J2EE-WG은 1차적으로 J2EE의 기반 구조를 제공해주는 ‘WAS 성능 향상을 위한 고려사항’을 제시하고자 한다(차후 기회가 되면 이런 기본 요소에 대한 부분도 다루도록 하겠다).

성능 향상을 위한 고려사항 선정
성능 향상을 위한 고려사항들은 J2EE 기반 시스템 구축 경험이 있는 J2EE-WG 회원들을 중심으로 선정되었다. 이러한 요소들은 현장에서 대부분 디폴트로 설정되고 있으며, 설정 변경보다는 시스템 용량(CPU, 메모리 등)을 늘리게 하는 주요 이슈들이다. 다음의 질문에 대한 각 벤더별 답변 내용의 주요 골자를 보며 고려되어야 할 사항들을 살펴보자(각 벤더의 답변 내용 중 오해의 소지가 있는 부분은 영문 그대로 실는다. 또한 각 벤더별 답변 원문은 ‘이달의 디스켓’을 참고하기 바란다).

짾 EJB 컨테이너 설정
짿 Deployment Descriptor 설정
쨁 패키징(packaging) 설정
쨂 트랜잭션 유형 설정
쨃 커넥션 풀링(connection pooling) 설정
쨄 기타 성능 향상 요소

EJB 컨테이너 설정
하나의 WAS에 여러 개의 컨테이너를 띄워서 시스템을 운영하는 경우가 많은데, 이때 각 컨테이너가 차지하는 시스템 리소스의 규모로 인해 컨테이너 설정이 전체적인 시스템 성능에 영향을 주고 있다. 컨테이너 설정을 어떻게 최적화해 운영·유지할 것인지 정확하게 입증하는 것은 중요한 이슈라고 생각된다. 컨테이너 수를 어떻게 결정하는지, 각 컨테이너는 어떻게 설정할 것인지 등에 대한 적정한 지표가 없어, 설정값이 대부분 디폴트로 설정되거나 벤더 기술 지원 인력의 주관적 경험에 의존해 결정되고 있다. 또한 업무 특성이 고려되지 않은 기술적인 접근은 실제 운영에 있어 예상치 못한 문제들을 발생시킬 수 있다. 기본 값이 아닌 다른 값으로 설정했을 때 발생될 수 있는 영향 혹은 문제점들에 대한 명확한 가이드라인의 부재로 인해, 업무 특성을 고려한 설정을 하려고 해도 어쩔 수 없이 디폴트로 운영하는 경우가 많다.

Q1. 컨테이너의 적정 개수 산정과 관련된 고려 사항

오라클 컨테이너에 있어 처리 가능한 트랜잭션 수는 시스템 리소스에 따라 많이 달라지며, 실제로는 최대로 수행 가능한 JVM 쓰레드의 수가 의미를 지닌다. 쓰레드 풀 사이즈의 설정을 통해 제어(공식적인 자료로는 ECperf 결과를 활용할 수 있다).
BEA 기본적으로 인스턴스 <= # of CPU(현재 1머신에서 8개인 인스턴스까지 사용하는 예가 있다)
IBM 케이스 1. 관련 EJB를 여러 개의 컨테이너에 분산시켜서 전개
- 성능적/비용적 측면에서 볼 때, 성능적 이점은 없이 JVM에 대한 프로세스 오버헤드만 존재할 뿐이다.
케이스 2. 모든 EJB를 하나의 컨테이너에 전개시키고 컨테이너를 복수 개로 클로닝(cloning)
- EJB 컨테니어에만 해당되는 특별한 고려사항은 없다.
- 웹 컨테이너 클러스터링시 개수 산정과 관련된 고려 사항과 같다.
썬 기본적으로 한 시스템 당 한 개의 컨테이너를 권장한다.

Q2. 복수의 컨테이너를 운용해야 할 경우 개수의 정확한 정의를 위해 제시하고 있는 권장사항

IBM 복수 개의 컨테이너 운용 목적 중에는 성능, 확장성, 신뢰성 등의 향상을 들 수 있다. 한 개의 머신에서 복수 개의 컨테이너를 운용하는 것에 대해선 대용량 시스템이어야 한다는 대전제를 필요로 한다. 특히 필요에 의한 복수의 컨테이너 운용은 업무별로 애플리케이션 서버를 분리해 운영하고자 하는 운영적인 측면에서 생각해 볼 수 있는데, 이는 그다지 바람직하지 않다(애플리케이션 서버 단위 → EAR 단위 업무 분리).

Q3. 설정항목, 설정 값의 저장위치와 항목별로 설정 값 변경시 발생할 수 있는 성능 영향

오라클 서버 설정을 위한 모든 항목은 XML 파일로 되어 있다.
server.xml : 메인 서버 설정
default-web-site.xml : 웹 서버 설정
rmi.xml : RMI 포트, 로그 등 설정
jms.xml : queues, topics, ports 등 설정
principals.xml : 사용자 및 역할 등 설정
data-sources.xml : DB 접근 제어 등 설정
global-web-application.xml : global Web applications 설정
application.xml : default application을 위한 설정
IBM 관리 콘솔을 통해서 설정할 수 있고, 그 값은 리파지토리 DB에 저장된다.
<캐시 크기>
- 캐시할 수 있는 인스턴스 수를 지정한다.
- 총 EJB 개수 X 동시사용자 수
- 지정된 값이 너무 작을 경우 성능저하의 원인이 된다.
<캐시 정리 간격>
- 컨테이너가 캐시 크기를 초과하지 않도록 캐시에서 사용되지 않은 항목을 제거하려고 시도하는 간격
- 일반적으로 캐시 크기를 증가시킨 것 만큼 간격도 증가시켜 준다.
<워크로드 관리 방침>
- 로컬 우선 라운드 로빙 방침이 라운드 로빙보다 성능이 더 좋다. 로컬 우선이란 EJB 클라이언트에서 EJB를 요청할 때 동일한 애플리케이션 서버에 있는 EJB 컨테이너 내의 EJB를 우선적으로 요청한다는 방침이다.
썬 server.xml에 있는 ejb-container 설정항목 중 다음을 유의해야 한다.
- steady-pool-size
- max-pool-size
- pool-resize-quantity
- pool-idle-timeout-in-seconds
- max-cache-size
- Cache-idle-timeout-in-seconds
- Removal-timeout-in-seconds

Q3의 경우 많은 기대를 했던 항목이지만 명쾌한 해답을 들을 수 없어서 아쉬웠던 부분이다. 업무 및 애플리케이션의 특성이 다양하기 때문에, 벤더에서도 케이스별 모범 답안을 제시하기가 어려웠던 내용이다. 그리하여 기술 지원을 하는 개개인의 역량과 경험에 따라서 시스템 성능이 좌우되는 현실을 경험할 수밖에 없는 것이다.

Deployment Descriptor
각 벤더에서 제공되는 가이드에는 Deployment Descriptor에 설정할 수 있는 항목들과 그에 대한 설명이 있지만 각 요소들이 실제로 시스템 성능에 어떠한 영향을 주는지 알 수 없기 때문에, 현실적으로는 대부분의 요소들을 디폴트로 설정하는 경우가 많다.
또한 Deployment가 정상적으로 이루어진 것처럼 보이지만 실제로 동작이 안되는 경우가 종종 발생하고 있으며, 일단 동작이 되면 그 자체에 만족하고 있기 때문에 성능에 대한 고려를 할 수 없는 환경이 만들어지고 있는 것이다.

Q4. 상황에 따라 여러 회사의 제품들이 함께 운영될 수 있는데, 이에 대한 가이드(예 : 웹 서버(A사) + 웹 컨테이너(B사) + 웹 애플리케이션 서버(C사) + DBMS(D사))

IBM < 툴 >
- 웹스피어는 텍스트 에디터를 통한 DD 직접 편집이 가능하지만 권장하지는 않는다.
- WSAD를 사용해서 개발할 경우, 개발과 동시에 웹스피어에 최적화된 DD가 자동으로 생성된다. 별도로 DD를 편집해야 할 경우에도 GUI를 통해 구조화된 방법으로 접근하기 때문에 쉽고 빠르게 작업할 수 있고 실수를 줄일 수 있다.
- WSAD 이외의 개발 툴을 사용할 경우에는, 웹스피어에서 제공하는 AAT(Application Assembly Tool)을 사용해서 역시 GUI로 작업할 수 있다.
< 튜토리얼 >
- DD는 HTTP Svr나 DB Svr의 종류에 독립적이다.
- 웹 애플리케이션(WAR), EJB(JAR), 엔터프라이즈 애플리케이션(EAR)의 DD 설정에 대해 쉽게 따라할 수 있는 튜토리얼이 웹으로 제공된다( http://www.ibm.com/software/webservers/appserv/ doc/v40/ae/infocenter/was/0607.html).
썬 Deployment Descriptor를 작성하는 가장 쉬운 방법은 썬원 스튜디오 4 IDE 또는 Administration 인터페이스를 사용한 EJB 모듈을 디플로이하는 것이다. 업데이트된 Deployment Descriptor 정보들은 제공되는 Ad ministration 인터페이스와 기타 유틸리티를 이용해 재설정할 수 있다.

‘한 벤더에서 모든 제품을 사야지 궁합이 잘 맞을까’라는 의문은 주위에서 쉽게 들을 수 있을 것이다. 표준 스펙은 따르고 있지만, 각 제품별로 벤더 나름대로의 특성들이 있기 때문에, 여러 벤더의 제품들을 조합하고자 할 때 혹은 조합해야 하는 경우에 어떠한 문제점들이 발생할 수 있고, 또 어떻게 조합하는 것이 좋은지 알고 싶었다. 그러나 벤더별 입장의 차이와 케이스별 조합이 매우 다양하다는 이유를 들면서 깊이 있는 답변을 주지 못하였다.

Q5. 주요 설정 항목(세부사항 : 퍼포먼스에 미치는 영향, WAS 설정 항목은 벤더별로 특성이 있는데, 각 벤더별로 유념해야 할 설정 항목들을 나열해 보았다)

오라클 server.xml에서 max-http-connections 설정에 유의
global-web-application.xml에서 main-mode 설정에 유의
web.xml에서 load-on-startup 설정에 유의
orion-ejb-jar.xml에서 do-select-before-insert 설정에 유의
orion-ejb-jar.xml에서 update-changed-fields-only 설정에 유의
orion-ejb-jar.xml에서 exclusive-write-access 설정에 유의
orion-ejb-jar.xml에서 isolation & locking-mode 설정에 유의
data-sources.xml에서 max-connections 설정에 유의
BEA 설정 값이 저장되어 있는 Weblogic-ejb-jar.xml 파일에서 다음 항목들 설정에 유의
- max-beans-in-free-pool
- initial-beans-in-free-pool
- max-bean-in-cache
- concurrency-strategy
- isolation-level
IBM 다음과 같은 설정항목에 유의
ibm-web-ext.xmi
ibm-ejb-jar-ext.xmi
썬 sun-ejb-jar.xml에서 풀링/캐싱 요소에 유의한다.
- Bean 풀 설정시
steady-pool-size
max-pool-size
pool-idle-timeout-in-seconds
Pool-resize-quantity
- Bean 캐시 설정시
max-cache-size
cache-resize-quantity
cache-idle-timeout-in-seconds
Victim-selection-policy

Q6. 운영 중인 WAS 상의 애플리케이션을 업데이트된 애플리케이션으로 교체하고자 할 경우 Deployment Descriptor 작성시에 고려되어져야 할 사항(Dynamic Deployment)

오라클 Deployment descriptor를 별도로 설정하지 않아도 변경된 클래스를 해당 디렉토리에 적용하면 자동적으로 dynamic deployement를 지원한다.
BEA 애플리케이션의 패키지 묶음
IBM 애플리케이션 서버를 재시작하지 않고도 애플리케이션 추가/변경 가능
웹 모듈
- JSP : DD의 설정과 관계없이 추가/변경 가능
- 서블릿 : 웹 애플리케이션 오토 리로딩이 true인 경우 추가/변경 가능
- 서블릿에서 참조하는 클래스나 Jar : 서블릿의 경우와 동일
- web.xml : 서블릿의 경우와 동일. 단, 다음의 경우는 해당 모듈 재시작 필요



- Web.xml에서 서블릿 맵핑 추가/변경시 HTTP Plugin configuration file 재생성 필요
- ibm-web-ext.xmi : 서블릿의 경우와 동일
- ibm-web-bnd.xmi : 해당 모듈 재시작 필요
-EJB 모듈
- ejb-jar.xml, ibm-ejb-jar-ext.xmi, ibm-ejb-jar-bnd.xmi : 변경시 모듈 재시작 필요
- Table.ddl : 변경시 DB 서버에서 재수행 필요
- Map.mapxmi, Schema.dbxmi : 변경시 EJB re-deploy, 모듈 재시작 필요
- EJB가 참조하는 클래tm나 Jar : 변경시 모듈 재시작 필요
- Home/Remote Interface class : 변경시 EJB re-deploy, 모듈 재시작 필요
썬 EJB 등의 일부 모듈이 변경된 경우에는 다시 디플로이를 한다든지, 서버를 재시작해야 할 필요는 없다. 변경된 파일(모듈)을 애플리케이션이 디플로이된 디렉토리(예 : instnce-dir/applications)에 넣어놓기만 하면 자동으로 변경된 것이 반영된다. Adminsration 인터페이스를 이용해 다이내믹 리로딩을 가능하게 하려면 다음과 같다.
짾 Adminsration 인터페이스에서 서버 인스턴스를 선택한다.
짿 애플리케이션을 선택한다.
쨁 애플리케이션의 설정 페이지들이 보여질 것이다.
쨂 ‘Reload Enabled’ 박스를 선택해 다이내믹 리로딩이 가능하도록 한다.
쨃 리로드되는 주기를 초단위로 입력한다(이 시간단위로 변화 여부가 체크된다).
쨄 설정을 저장한다.

Dynamic Deployment는 벤더 모두 지원한다는 입장을 보였으며, 고려되어야 할 사항보다는 어떻게 Dynamic Deployment를 하는지 알려주는 정도의 답변이었다.

패키징 설정
J2EE 기반의 애플리케이션은 HTML, XML, 서블릿, JSP, EJB 등과 같은 요소들로 구성되어 있으며 업무별, 기능별, 혹은 기타 다양한 원칙에 따라 JAR/WAR/EAR의 형태로 패키징된다. 그러나 각종 패키지들이 모호한 원칙에 따라 다양한 형태와 크기로 등록·설치되어 사용되고 있는 실정이므로, 패키징의 기술적인 제약사항, 기본요건, WAS간 호환 문제 해결 등을 위한 관련 가이드의 필요성이 제기되었다.

Q7. 패키징 단위 설정에 대한 권고사항(업무별, 기능별, 사용빈도별, 중요도별 등)

오라클 업무 프로젝트별 패키징을 권장
BEA 상황에 따라 다름. 그러나 관리가 따로 되는 단위가 제안됨
IBM 웹 모듈의 경우 HttpSession의 공유를 고려해야 한다.
J2EE 환경에서 HttpSession의 범위는 각 웹 애플리케이션으로 제한되기 때문에, HttpSession을 공유해야 할 서블릿/JSP는 동일한 웹 모듈 안에 있어야 한다.
썬 Type of Development Group
Small workgroup
Enterprise workgroup
Teams in Group
1 web team + 1 EJB team
2 EJB teams + 1 web team + 1 component
Modularizing Scheme
1 EAR = 1 EJB + 1 WAR
1 EAR = 2 EJB + 1 WAR + 1 individual component

Q8. 패키징의 기술적 제약사항 및 기본 요건

IBM 웹 모듈의 경우 HttpSession의 공유를 고려해야 한다.
특별한 제약사항은 없다.
Common code(common/utility class or Jar)의 위치는 다음 두 가지 중에서 상황에 맞는 것으로 선택
- Common classpath에 놓는다(Runtime Sharing)
소스 관리가 용이/약간의 시스템 자원 절약
- 각각의 EAR마다 하나씩 포함시킨다
애플리케이션이 서로에 대해 독립적

Q9. 패키징 사이즈에 따른 성능에의 영향과 근거

오라클 큰 패키지 사이즈는 수행 성능에는 문제가 없지만 개발시에 긴 설치 시간 및 메모리 점유로 인한 성능적인 부담을 줄 수 있음
BEA 상관 관계에 대한 문서는 아직 없음. 메모리에 많이 올라가서 많은 프로그램을 처리하는 것은 부하가 될 수 있음
IBM JDK 1.3.X에서 효율적으로 사용할 수 있는 애플리케이션 힙 사이즈의 한계는 대략 1.2GB다. 애플리케이션이 이 힙 사이즈 안에서 과도한 가비지 컬렉션 없이도 잘 수행된다면 패키징 사이즈는 성능과 직접적인 관계가 없다. 패키징 사이즈보다는 애플리케이션의 디자인과 코딩 기법이 성능에 미치는 영향이 훨씬 크다. 웹스피어 디벨로퍼 도메인에서 성능 향상을 위한 다양한 실전 예제를 찾아 볼 수 있다(http://www7b.soft ware.ibm.com/wsdd/zones/bp/).

Q10. WAS간 호환 문제를 해결하기 위한 패키징 방안

오라클 소스에는 영향이 없음. Deployment descriptor만 플랫폼에 맞추어 설정을 변경해 주면 됨
BEA 소스는 그대로 사용하고 포팅시에 Deployment Descriptor를 재작성할 필요가 있음
IBM 기본적으로 J2EE 표준 DD만 사용해서 패키징한 애플리케이션은 WAS 벤더에 비종속적으로 디플로이할 수 있다. WAS 벤더의 확장 DD를 사용할 경우에는 타 벤더와 호환되지 않기 때문에 디플로이하기 전에 확장 DD를 편집해 주어야 한다. WAS간 호환을 위해서는 벤더 확장 DD를 사용하지 않는 방법이 최선이다.

트랜잭션 유형 설정
트랜잭션의 설정은 중요한 자원에 대한 변경 관리시에 매우 중요한 사안이며, 그 관리를 위해서는 많은 시스템 자원이 필요하게 된다. 그러나 트랜잭션 관리가 필요하지 않은 경우가 있음에도 불구하고 트랜잭션 관리 범위를 확대함으로써 시스템 자원이 불필요하게 낭비되는 결과를 초래하는 경우가 많기 때문에, 트랜잭션 관리의 원칙을 도출하는 것은 중요한 의미를 가진다. 특히, CMT(Container Managed Transaction)보다는 BMT(Bean Managed Transaction)가 더 효과적인 경우에도 개발자의 기술 의존도가 높아지기 때문에 CMT를 선호하고 있으며, 트랜잭션 옵션 설정이 시스템 성능에 미치는 영향에 대한 확신이 부족하기 때문에 Transacti on_Required와 같은 값으로 설정하는 경우가 대부분이다.

Q11. CMT vs. BMT
트랜잭션 유형의 설정은 극단적으로 얘기하면 ‘개발자에 대한 믿음’과 ‘트랜잭션 유형을 염두에 둔 개발 표준에 대한 믿음’의 정도에 따라서 결정할 수 있다. 벤더의 입장도 개발자의 실수만 아니라면 BMT로 설정하는 것이 성능향상에 도움이 된다고 생각하고 있다. 결국 표준화가 철저하게 검증되어 지켜지고 있는 경우에만 BMT로 설정해 사용하라는 권고를 하고 있다. 사실 우리는 ‘BMT로 설정하고 또 BMP(Bean Managed Persistence)로 설정한다면 EJB를 왜 사용하는가?’라는 질문을 하였지만 논리적인 답변을 받을 수는 없었다. 다만 트랜잭션 유형 결정은 개발자의 실력과 그에 대한 믿음 그리고 개발표준 등의 정도에 따라서 이루어질 수 있다는데 공감하였다.

Q12. 트랜잭션 isolation에 대한 가이드라인

오라클 isolation 및 잠금 모드(locking mode)의 설정을 지원
BEA DB에 의존적임
IBM 대부분 트랜잭션 isolation 레벨은 데이터베이스 기본 isolation 레벨인 ‘Read Committed’를 그대로 따른다. 데이터 일관성의 문제는 성능의 문제보다 더 심각하기 때문에 불확실할 경우 ‘Serializable’을 선택한다. 만약 성능이 문제가 된다면 나중에 당황하지 않도록 낮은 isolation 레벨도 견딜 수 있는 트랜잭션을 작성하도록 개발할 때 신중하게 생각해 봐야 한다.
썬 server.xml 에 있는 ‘transaction-isolation-level’은 풀링된 DB 커넥션에 대한 레벨을 나타낸다. 이 셋팅은 선택적으로 할 수 있으며 디폴트는 없다. 명시되지 않으면 JDBC 드라이버에 설정된 isolation 레벨로 설정될 것이다. 설정 값에는 read-uncommitted, read-committed, repeatable-read, serializable 등이 있다. 설정 값은 트랜잭션이 진행 중에 변경해서는 안된다. 또한 연결된 DB의 특성을 잘 파악하여야 한다. 참고로, Isolation 레벨 설정에 관한 사항들은 J2EE 플랫폼에서 표준화되지 않았다.

커넥션 풀링 설정
과거 DB 커넥션 자체에 많은 부하가 발생됐으나, 커넥션 풀링을 통해 시스템의 성능향상이 이루어졌다. 그러나 한정된 자원을 활용해 더욱더 안정적인 성능을 보장하기 위해서는 커넥션 풀링의 효율적 관리 방안이 도출되어야 한다. 커넥션 풀링 관련 가이드는 실제로 존재하지만, 설정 값 변경에 따른 시스템 성능에의 영향을 명확히 알지 못하기 때문에 자신감 있게 환경 설정을 하지 못하는 원인이 되고 있다.

Q13. 커넥션 풀링 관련 프로퍼티 설정 가이드 및 설정 근거와 성능에의 영향(min/max pool size, connection/idle/orphan ti meout, statement/preparedStatment cache size 등)

오라클 JDBC 커넥션 외에 HTTP 커넥션 등 종합적인 커넥션 리소스가 관리되어야 한다.
Data-source 최대 커넥션 수 >= (모든 JVM을 걸친) 동시 유효 쓰레드 수의 최대치
쓰레드가 무제한이거나, DB concurrency에 병목현상이 있는 경우에는 좀더 낮춰야 한다.
커넥션이 지속적으로 최대로 사용되고 있으면 wait-time을 조정해야 한다.
BEA InitialCapacity와 MaxCapacity의 개수를 동일하게 지정
- Caching Prepared Statement
- 성능 향상에 매우 도움이 됨
- 웹로직 콘솔에서 설정
- WLS가 애플리케이션이나 EJB에서 사용된 Prepared statement를 저장한다.
- 제약 사항 : 데이터베이스의 테이블이 삭제되었다가 재생성되거나, 컬럼이 추가 혹은 변경되는 경우는 에러가 날 수 있음
IBM Max : Burstness factora→0/부족하지 않으면 충분/Active 유저의 개수에 근접
Min : 첫 접속시에만 이슈
PreparedStatement cache : 빈번히 사용되는 pstmt # x Active 유저
썬 - setTransactionIsolationLevel()로 설정하기 보다는 드라이버에서 설정된 디폴트 isolation 레벨을 사용하는 것을 권장한다(idle time = 0).
- max-wait-time-in-millis = 0
- ‘Transcation-isolation-level’을 수정하는 것은 자제할 것을 권장한다.
- connection-validation-required = true로 설정할 것을 권장한다. 이는 DB 커넥션이 풀에 반환될 때마다 커넥션의 상태를 점검해준다.

Q14. 기술지원에 참여했던 안좋은 경우와 솔루션

IBM 상대적으로 최대 값을 100, 300, 500, 1000 등 불필요하게 높게 책정하는 경향이 있음. 권장사항은 Active 유저의 개수 근방에서 조정

기타 성능 향상을 위한 고려 사항
Q15. WAS 제품의 각 O/S별 최적 운용을 위한 파라미터 설정 가이드라인

오라클 네트워크(TCP) 파라미터 설정
tcp_conn_hash_size 32768
tcp_conn_req_max_q 1024
tcp_conn_ req_max_q0 1024
tcp_recv_hiwat 32768
tcp_slow_start_initial 2
tcp_close_wait_interval 60000
tcp_time_wait_interval 60000
tcp_xmit_hiwat 32768
BEA http://edocs.bea.com/wls/certifications/certifications/index.html를 참조한다.
IBM 웹스피어 애플리케이션 서버 4.0 InfoCenter
http://www-3.ibm.com/software/webservers/appserv/ infocenter.html
IBM WebSphere Redbooks
http://www.redbooks.ibm.com
468 웹스피어 추천 문서모음
http://www.javaservice.com/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=1010952419
140 웹스피어 V3 퍼포먼스 튜닝 가이드
http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=959577074
301 벤치마크 테스트를 위한 퍼포먼스 튜닝 퀵가이드
http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=985764595
[강좌] 웹 기반 시스템에서의 성능에 대한 이론적 고찰
http://www.javaservice.net/~java/bbs/read.cgi?m=resource&b=consult&c=r_p&n=1008701211
405 웹 사이트 분석 방법 및 용량산정 팁
http://www.javaservice.net/~java/bbs/read.cgi?m=qna&b=consult&c=r_p&n=1015965697

Q16. 가비지 컬렉션 관련 설정 가이드라인

오라클 가비지 컬렉션 튜닝시에는 총 힙 메모리를 유념해야 한다.
힙 메모리는 기본적으로 가비지 컬렉션에 의해서 늘어나기도 하고 줄어들기도 한다.
또한 JVM은 사전에 정해진 특정 비율로 빈 메모리 공간을 유지하려는 특성이 있다.
목표 범위는 다음과 같은 형태로 설정할 수 있다.
-XX:MinHeapFreeRatio=
-XX:MaxHeapFreeRatio=
최대 범위는 ?Xms ~ ?Xmx 사이가 된다.
<키 포인트>
JVM에 기본적으로 할당된 메모리는 매우 적은 편이기 때문에, 별다른 문제가 없는 한 JVM에 메모리를 많이 할당해주어야 한다.
Xms와 Xmx는 같은 수치로 설정한다(물론 값에 대한 테스트는 수행되어야 한다).
프로세서를 증설하면 메모리를 늘려주어야 한다.
메모리 점유는 병렬적으로 일어나지만, 가비지 컬렉션은 그렇지 않음에 유의하라.
Another important tuning item is sizing the area of the heap dedicated to the young generation
BEA Java ?verbosegc : 가비지 컬렉션이 얼마나 자주 일어나는지 알 수 있음
힙 메모리 최소/최대 동일하게 설정
로우 메모리 설정 가능
IBM JDK 1.2 < JDK 1.3 이상에서는 가비지 컬렉션의 영향도는 없음
Xms 및 Xmx 값이 중요하며, 128-256-512m 정도 설정
썬 - Garbage collection reclaims the heap space previously allocated to objects no longer needed. The process of locating and removing the dead objects can stall any application while consuming as much as 25 percent throughput.
young generation 사이즈를 적절히 고려해 JVM에 충분한 메모리를 할당해야 한다.
JVM1.4를 위한 디폴트는 NewRatio 값과 -Xmx 값을 고려해 설정되어 있다.
- 솔라리스 시스템을 위한 설정의 예제를 살펴보자.
-Xms3584m
-Xmx3584m
-Xss128k
-Xnoclassgc
-verbose:gc
-Dsun.rmi.dgc.client.gcInterval=3600000

Q17. 쓰레드 관련 파라미터 설정 가이드라인

오라클 사용자의 부하가 큰 경우에는 쓰레드 수를 제한해야 하지만 시스템 리소스가 충분한 경우에는 쓰레드 수를 늘려준다.
최대 쓰레드 개수를 안다면 쓰레드 튜닝은 다음과 같이 두 형태로 할 수 있다.
짾 큐 사이지를 최대 쓰레드 수의 두 배로 설정한다.
짿 min=max로 설정하고 keepAlive=-1(쓰레드 타임아웃을 없앰)
BEA Unix Threading model : Green/native 쓰레드 방식, 더 좋은 성능을 위해 네이티브 쓰레드를 사용함.
ThreadCount : Default: 15/# of CPU수가 비교해 설정한다. 큐(Queue)에 쌓이지 않도록 한다.
StuckThreadMaxTime : Default: 600초/서버가 stuck되었다고 판단하는 기준 시간, Node Manager로 restart함.
ThreadPoolPercentSocketReaders : Default: 33/쓰레드 중 일부를 클라이언트 요청을 받는데 읽도록 할당
IBM Xss(native stack size) 값이 작아야 더욱 많은 쓰레드를 생성할 수 있음.


시스템 성능향상을 위한 과제
시스템의 성능에 문제가 발생하면 대게는 기술적으로만 접근하는 오류를 범한다. 또한 최근에 나온 기술이면 모든 것이 해결될 것이라고 생각하고 문제가 생기면 검증되지 않은 기술을 도입했기 때문이라고 책임을 회피하는 경우도 많다. 최고의 아키텍트는 특정 도메인의 특성에 해박하고, 업무 모델링, 인프라스트럭처와 애플리케이션에 대한 식견, 그리고 그 모두의 코디네이션(Coordination)에 능해야 한다고 혹자는 말한다. 그만큼 도메인(비즈니스)에 대한 이해가 기본적으로 필요하다는 것이다. 도메인에 대한 이해가 없는 기술적 접근은 필요 이상의 기술을 도입하게 할 수 있으며, 시스템 성능 점검시 잘못된 판단을 할 수 있다. 새로운 기술을 사랑하는 만큼 내가 개발하고 있는 업무 특성에도 관심을 가져보자.
그러나 WAS 관리자가 아무리 업무 특성을 잘 파악하고, 적극적으로 설정 변경을 주장한다 할지라도, 프로젝트의 특성상 ‘책임’ 문제가 있기 때문에, 많은 WAS 관리자들이 망설이고 있다. 이는 단순히 몇몇 사람이 해결할 수 있는 사항이 아니라 ‘성능 향상을 위한 튜닝 작업 절차’의 정형화와 정책적인 지원이 제도적으로 이루어 져야만 한다. 또한 성능을 고려하지 않는 방법론과 업무 모델링과 그리고 구현은 큰 문제가 아닐 수 없다. 시스템의 기능(functional requireme nts)만 만족하게 하고, 나중에서야 급급하게 시스템의 성능(nonfunctional requirements)을 고려하는 단기적인 시각은 반드시 고쳐져야 할 것이다. 성능을 전혀 고려하지 않은 상태에서 몇 가지 설정만 바꾸어서 일시적으로 성능이 향상되었다고 할지라도 근본적인 시스템 효율성은 향상될 수 없는 것이다.
성능이 안정화되기 위해서는 많은 부분에 노력이 필요하지만, J2EE-WG은 그 중에서 ‘성능 향상을 위한 WAS 설정’을 고민해 보았다. 고민의 흔적을 보면서 느꼈겠지만 고민을 풀어줄 해답은 아직 명쾌하게 정리되지 않았다. 아마도 국내 대부분의 기업 내부에서도 본지에서 다루었던 이슈들에 대해 문서화된 명확한 가이드라인을 제시하기는 힘들 것이다. 내부적으로 정리되지 않았던 노하우와 성능 관련 중요한 이슈들을 이제부터는 함께 정리해 보았으면 한다. 목마른 사람은 물을 찾게 되어 있지만, 마실 수 있는 물을 혼자 찾아야 한다면 그 만큼 절망적인 현실은 없을 것이다. 내가 알고 있는 길, 그 길에 대한 감각이 희미할 지라고 함께 찾았으면 한다. ‘우리는 명쾌한 가이드라인이 있는데’라고 하는 독자 혹은 함께 고민하고 싶은 사람이 있다면 서로에 대한 노하우를 전수받을 수 있는 소중한 자리가 마련되었으면 한다. 그리고 WAS 벤더들이 앞으로 만들어질 소중한 자리에서 소극적인 기존의 모습에서 벗어나 주도적으로 활동할 것을 기대한다.

정리 | 조규형 | jokyu@korea.cnet.com

 

출처 : http://www.imaso.co.kr/?doc=bbs/gnuboard_pdf.php&bo_table=article&page=3&wr_id=913&publishdate=20030401

:
Posted by 라면스프
2008. 10. 23. 18:06

windows regedit 분석 Enjoy/etc2008. 10. 23. 18:06

출처 : http://boanchanggo.tistory.com/62

windows regedit 분석

□ 레지스트리 편집기를 열면 다음과 같은 항목들이 나온다.
▤ HKEY_CLASSES_ROOT
▤ HKEY_CURRENT_USER
▤ KEY_LOCAL_MACHINE
▤ HKEY_USERS
▤ HKEY_CURRENT_CONFIG 
 
레지스트리는 윈도우의 정보를 담고 있는 일종의 Database라고 이미 설명했다.
위의 항목들이 무엇을 뜻하는지 항목 하나하나를 살펴보도록 하자.
 

 
① HKEY_CLASSES_ROOT
  • HKEY_CLASSES_ROOT*shellex ContextMenuHandlers
    마우스 오른쪽 버튼에 추가되는 응용프로그램에 대한 정보

  • HKEY_CLASSES_ROOTCLSID {645FF040-5081-101B-9F08-00AA002F954E}
    운영체제에서 사용되는 파일들의 확장자에 대한 정의와 실행
    - 바탕화면의 휴지통의 이름은 여기서 변경할 수가 있다.
② HKEY_CURRENT_USER
  • 현재 사용자가 사용하는 응용프로그램들에 대한 여러 가지 환경설정이 기록된다. 뿐만아니라 윈도우98의 각 구성 요소들에 대한 정보 역시 이곳에 저장이 되어 사용된다.

  • HKEY_CURRENT_USERAppEvents
    EventLabels
    윈도우에서 일어나는 음향 설정에 관한 레지스트리 키. 제어판의 사운드 등록정보에서 확인할 수 있다.

    Schemes
    현재 윈도우의 음향에 적용된 효과음에 대한 설정 키들. 윈도우 자체의 음향뿐 아니라 응용프로그램을 인스톨해 설정되는 음향 설정까지 모두 포한다 (예: 한글 시작시 나오는 사운드).

    HKEY_CURRENT_USERAppEventsSchemesNames
    사운드 등록정보의 사운드 구성표의 내용.

  • HKEY_CURRENT_USERControl Panel
    제어판에 대한 설정뿐 아니라 데스크탑에 대한 설정까지 포함하고 있다.

    • HKEY_CURRENT_USERControl PanelAppearanceSchemes
      디스플레이 등록정보의 화면배색이라는 대화상자속에 포함되어있는 색구성표의 목록이다.

    • HKEY_CURRENT_USERControl PanelAppearanceColors
      현재 적용해 사용하고 있는 각각의 색에 대한 설정값.

    • HKEY_CURRENT_USERControl PanelCursorsSchemes
      마우스 등록정보의 포인터항목에 위치한 마우스 구성표이다.

    • HKEY_CURRENT_USERControl PanelKeyboard
      keyboardSpeed 항목의 값이 31이면 키의 반복속도는 최대한 빠르게 설정된 상태이다.

    • HKEY_CURRENT_USERControl PanelPowerCfgPowerPolicies
      전원관리 등록정보의 전원 구성표 목록이다.

    • HKEY_CURRENT_USERControl Paneldesktop
      MenuShowDelay 키를 만든후 그 값을 0으로... 그럼 메뉴 열리는 속도가 왕 빨라진다.

    • HKEY_CURRENT_USERControl PaneldesktopWindowMetrics
      Shell Icon BPP라는 키를 살펴보자. 이 키값이 16이면 하이컬러로 아이콘이 보인다.

  • HKEY_CURRENT_USERInstallLocationsMRU
    플로피 디스크나 하드디스크의 특정 위치에서 하드웨어의 드라이버를 설치했을 경우 그 정보들이 여기에 기록된다. 플로피 디스크 드라이버의 경우 삭제해도 소용없다.

  • HKEY_CURRENT_USERkeyboard layout
    제어판의 키보드 등록정보 안에 있는 설치된 키보드 언어 및 키 배치의 내용이다. 일반적으로 한국어로 등록이 되어있기 때문에 기본키값은 412이다.

  • HKEY_CURRENT_USERNetwork
    네트워크이용시 네트워크 드라이브에 대한 설정이 저장된다.

  • HKEY_CURRENT_USERRemoteAccess
    전화접속 네트워킹의 구성내용을 저장.

  • HKEY_CURRENT_USERSOFTWARE
    사용자가 윈도우98에 설치한 응용 프로그램의 구체적인 정보를 저장한다. 예를 들면 응용 프로그램에서 사용하는 하드웨어 드라이버라든가 프로그램의 툴바의 배치상태, 색상, 사용자가 지정한 옵션들에 대한 것들이 저장되어 있다. 대개 바이너리 형태로 저장되므로 직접 편집하기는 거의 불가능하다. 따라서 해당프로그램의 옵션에서 조정해주는 방식을 이용해야 한다.

    • HKEY_CURRENT_USERSOFTWAREMicrosoft
      윈도우98에 기본으로 깔리게 되는 응용 프로그램들에 대한 설정이 저장된다. 또한 현재 윈도우 설정에 대한 정보 역시 상당히 많이 가지고 있어서 레지스트리에서 가장 중요한 부분에 속한다.

    • HKEY_CURRENT_USERSOFTWAREMicrosoftActiveMoviedevenum
      제어판의 멀티미디어 부분에 대한 정보가 여기에 저장되어 있다.

    • HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerDesktop
      윈도우98의 액티브 데스크탑에 대한 설정이 저장됨.

    • HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMain
      인터넷 익스플로어 4.0의 초기 셋업에 대한 옵션

    • HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerTypedURLs
      인터넷 익스플로어의 주소창에 타이핑했던 주소들을 저장.

    • HKEY_CURRENT_USERSOFTWAREMicrosoftMultimediaAudio
      윈도우95의 멀티미디어 등록정보에서 볼 수 있었던 라디오 음질, CD 음질, 전화 음질을 찾을수 있다.

    • HKEY_CURRENT_USERSOFTWAREMicrosoftWABServer Properties
      디렉토리서비스를 지원하는 사이트의 목록

  • HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionExplorerRecentDocs
    시작버튼에 등록되어 있는 문서메뉴의 내용이다.

    HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionExplorerRunMRU
    실행창에서 실행시켰던 명령어들이 기록된다.

  • HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRun
    윈도우의 시동시 자동으로 시작되는 프로그램을 정의.

③ HKEY_LOCAL_MACHINE
윈도우 시동에 필요한 모든 하드웨어, 소프트웨어의 정보가 모여있다. 윈도우를 처음으로 설치했을 때 그 내용이 구성되며, 장치관리자를 애용해 하드웨어 구성내용을 변경할 수 있다. 따라서 이부분을 건들일때에는 각별히 신경을 써야 한다.

  • HKEY_LOCAL_MACHINEConfig
    현재 사용자의 시스템 구성상황을 저장하는 곳이다. 시스템 등록정보의 하드웨어 초기화 파일에 있는 Original Configuration의 내용이 바로 여기에 등록 된다. 기타 하드웨어 초기화 파일이 여러 개일 때는 Config 키 밑에 0002, 0003 과 같은 서브 키가 새로 생겨 이를 저장한다.

  • HKEY_LOCAL_MACHINEConfig001DisplaySettings
    이곳은 현재 사용자가 사용하는 디스플레이에 대한 세팅을 조정할 수 있다.
    DPILogicalX 값과 DPILogicalY 값을 변경해 모든 윈도우 폰트 크기를 조정할 수 있다.

  • HKEY_LOCAL_MACHINEEnum
    장치관리자에서 관리하는 트리구조의 하드웨어 설정을 기록하고 있다.

  • HKEY_LOCAL_MACHINEEnumBIOS
    하드웨어를 처음으로 설치할 때 지정한 PNP기기의 설정 값이 기록되어 있다. 시스템 타이머, 직접 메모리 엑세스 컨트롤러, 통신포트 등이 이에 해당한다.

  • HKEY_LOCAL_MACHINEEnumESDI
    하드디스크 구성에 대한 기록. 이것은 하드디스크의 개수에 따라 따로 따로 설정 된다.

  • HKEY_LOCAL_MACHINEEnumFLOP
    플로피 디스크에 대한 하드웨어 구성을 담고 있다.

  • HKEY_LOCAL_MACHINEEnumINFRARED
    적외선 장치에 대한 설정.

  • HKEY_LOCAL_MACHINEEnumISAPNP ISA
    슬롯에 장착되어 있는 PNP기기에 대한 설정을 포함. 사운드 카드와 사운드 카드에 포함된 게임 포트, IDE 컨트롤러 등 역시 여기에 설정된다.

  • HKEY_LOCAL_MACHINEEnumLPTENUM LPT
    포트에 대한 설정 내용이 기록되며 이곳에 연결된 장치 역시 여기에 설정되어 있다. 대표적으로 프린터가 그 예이다.

  • HKEY_LOCAL_MACHINEEnumMF
    마더 보드에 있는 E-IDE 컨트롤러에 대한 설정이 기록되어 있다.

  • HKEY_LOCAL_MACHINEEnumMONITOR
    모니터 구성에 대한 기록되어 있다.

  • HKEY_LOCAL_MACHINEEnumNetwork
    시스템에 설치된 네트워크 구성요소들에 대한 설정이 포함되어 있다. 마이크로 소프트 네트워크 클라이언트, 전화 접속 어뎁터, 마이크로 소프트 네트워크 파일/프린터 공유 프로그램, NetBEUI, IPX/SPX 호환 프로토콜, TCP/IP등이 이에 해당한다.

  • HKEY_LOCAL_MACHINEEnumPCI
    시스템에 설치된 PCI기기와 PCI에 관계되는 Intel 82439TX Pentium(r) Processor to PCI bridge, PCI 스티어링을 위한 IRQ 홀더, Intel 82371AB/EB PCI Bus Master IDE Controller등 PCI슬롯과 연결되어 있는 모든 장치에 대한 설정이 모여 있다.

  • HKEY_LOCAL_MACHINEEnumRoot
    시동할 때 윈도우가 하드웨어를 정상적으로 인식하기 위해 참고하는 바이오스 설정 내용들이 지정되어 있다. 보드가 지원하는 플러그 앤 플레이 바이오스나 마더보드의 바이오스 버전, 전원 관리 등에 대한 설정이다.
    그리고 시동 때마다 새로 읽어들이는 마우스와 같은 장치들을 설정해 둔다. PNP를 완벽하게 지원하지 못하는 하드웨어(LAN 카드, 모뎀)가 있는 경우 이미 구성되어 있는 데이터 베이스 파일(C:WINDOWSINFMACHINE.INF)을 참조하여 키를 구성한다.

  • HKEY_LOCAL_MACHINEEnumSCSI
    스카시 기기에 대한 구성이 저장되는데 일반적으로 시디롬 구성정보 역시 이곳에 있다.

  • HKEY_LOCAL_MACHINEEnumUSB
    USB 컨트롤러에 대한 설정이 기록된다.

  • HKEY_LOCAL_MACHINEHardware
    시스템에 설치되어 있는 하드웨어 목록이 기록되어 있다. 구체적인 설정내용이 있는 것이 아니라 단순한 정보만 저장되어 있다.

  • HKEY_LOCAL_MACHINEHardwareDescript-xionSystem
    이 아래에는 몇개의 서브키가 존재한다. CentralProcessor 키에서는 CPU에 대한 정보가 기록되어 있으며 FloatingPointProcessor키에는 외부 포인터 장치에 대한 정보가 기록된다.

  • HKEY_LOCAL_MACHINEHardwareDescript-xionSystemCentralProcessor
    여기에 있는 서브키중 VendorIdentifier의 내용인 GenuineIntel을 Genuine Intel로 고친다. 그러면 시스템 등록정보의 일반항목에서 현재 자신의 CPU에 대한 정확한 정보를 알수가 있다. 참고로 펜티엄166MMX의 경우에는 x86 Family 5 Model 4 Stepping 3 이다. 펜티엄133 인경우에는 x86 Family 5 Model 2 Stepping 12이다.

  • HKEY_LOCAL_MACHINEHardwaredevicemap
    현재 시스템에 있는 시리얼 포트의 이름이 기록되어 있다.

  • HKEY_LOCAL_MACHINEHardwareDirectDrawDrivers
    다이렉트 드로우를 구동하기 위한 드라이버의 이름이 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftware
    시스템에 설치된 소프트웨어에 대한 정보를 저장하고 있다. 주로 프로그램의 환경설정에 대한 구체적인 정보를 저장한다. HKEY_LOCAL_MACHINESoftwareCLASSES HKEY_CLASSES_ROOT의 키값과 동일한 값을 가진다.

  • HKEY_LOCAL_MACHINESoftwareClientsContacts
    윈도우98의 주소록에 대한 설정이 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftwareClientsInternet Call
    윈도우98의 넷미팅에 대한 설정이 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftwareClientsMail
    윈도우98에서 사용하는 전자메일 클라이언트에 대한 설정이 기록되어 있다. 윈도우98에서는 아웃룩 익스프레스가 기본으로 깔리기 때문에 이것의 설정이 여기에 있다.

  • HKEY_LOCAL_MACHINESoftwareClientsNews
    역시 뉴스 클라이언트에 대한 설정 내용이 여기에 있다. 아웃룩 익스프레스의 뉴스리더의 설정이 저장된다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoft
    윈도우98의 구성요소들에 대한 정보들이 모두 여기에 모여있다. 따라서 윈도우98의 레지스트리 중 가장 중요한 부분 중의 하나이다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftActive SetupInstall Check
    현재 윈도우98에 설치되어 있는 인터넷 익스플로어의 버전 정보가 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftActive_SetupInstalled Components
    윈도우98을 처음 설치했을 때 사용자가 설정한 시스템 구성요소에 대한 정보가 기록되어 있다. 따라서 윈도우98의 구성요소를 추가할때는 먼저 이곳의 정보를 읽어들여서 나타내는 것이다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftAdvanced INF Setup
    인터넷 익스플로어4.0의 삭제 정보가 여기에 기록되어 있는데, 이것은 C:Program FilesUninstall Information의 파일을 이용하게 된다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftConferencingCaptureDevices
    동화상을 캡쳐하기 위한 하드웨어에 대한 데이터 베이스가 여기 있다. 필요없는 것들은 지워주는 것이 좋다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftInternet ExplorerAdvancedOptions
    제어판의 인터넷 등록정보 대화상자의 고급 항목 내용이 저장되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftInternet ExplorerMainUrlTemplate
    인터넷 익스플로어4.0에서 사용하는 자동 완성 데이터가 여기 수록된다. com, edu, org만 기본으로 지원한다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!
    윈도우98에 기본으로 설치되는 테마 이외의 기타 테마에 대해 설정되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!System AgentSAGECompression Agent
    압축 에이전트 디스크 공간 늘림3에 대한 설정이 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!System AgentSAGEDisk Cleanup
    디스크 정리 프로그램에 대한 설정 내용일 여기에 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!System AgentSAGEDisk Defragmenter
    디스크 조각모음에 대한 설정 기록.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!System AgentSAGELow disk space notification
    디스크 공간 부족을 경고하는 것에 대한 설정 기록.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftPlus!System AgentSAGEScandisk for Windows
    디스크 오류 검사에 대한 설정 기록.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftShared ToolsMSInfo
    마이크로 소프트 시스템 정보라는 유틸에 대한 설정이 기록된다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersion
    시스템 등록정보에 보이는 여러 가지 항목들을 수정할 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionApp Paths
    윈도우98에 설치되어 있는 각 프로그램의 실행 파일 경로가 기록되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionAppletsCheck DriveLastCheck
    하드디스크 오류 검사 결과를 여기에 기록해 두는데, 나중에 다시 검사할 때 이 정보를 참고한다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionexplorerAdvanced
    탐색기 옵션을 저장함.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionexplorerAutoComplete
    자동완성 기능을 사용할 것인지 여기에서 결정할 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionexplorer
    MyComputerNameSpace
    내 컴퓨터에 있는 전화접속 네트워킹 아이콘과 예약된 작업 아이콘의 표시 유무를 기록.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionexplorerSmallIcons
    탐색기나 폴더의 도구모음 아이콘을 크거나 작게 조절할 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionexplorerThumbnail View
    이미지 파일이나 WAV파일과 같은 일부 멀티미디어 파일인 경우 폴더를 웹형식으로 보면 해당 파일들을 미리보거나 연주할 수 있다. 여기에서는 미리 연주 기능만 켜고 끌 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionFonts
    윈도우에 등록된 폰트들을 저장한다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionFS Templates
    컴퓨터의 용도를 지정한다. 즉, 데스크탑 컴퓨터인지 도킹 시스템인지 네트워크 서버인지 등을 지정한다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionInternet Settings
    인터넷 익스플로러에 사용되는 모든 설정 내용을 저장하고 있다. 히스토리나 캐시 파일의 위치, 쿠키 디렉토리 그리고 액티브X의 사용 여부, 자바 스크립트 사용 여부 등의 옵션을 저장한다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionMS-DOSOptions
    윈도우98 폴더에 있는 '게임용 MS-DOS 모드'라는 단축아이콘을 클릭하면 그에 대한 등록정보 대화상자가 나타난다. 이때 프로그램 항목에서 고급이라는 단추를 눌러주면 config.sys와 autoexec.bat를 구성하는 대화상자가 나타난다. 하단의 구성 버튼을 눌러주면 나타나는 MS-DOS 구성 옵션 선택 대화상자의 옵션들이 나타나는데 이 옵션 정보가 여기에 저장되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionrun
    윈도우를 시동할 때 시스템에 상주하는 프로그램에 대한 설정이 여기에 기록되어 있다. CTRL+ALT+DEL키를 누르면 확인할 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionTime Zones
    기준 시간에 대한 목록이 기록되어 있다. 레지스트리 크기를 줄이려면 필요없는 내용들을 지워도 좋다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersion Uninstall
    제어판의 프로그램 추가/삭제 등록 정보에 수록되어 있는 프로그램 항목들이 여기에 수록되어 있다. 프로그램을 삭제한 다음에도 여전히 기록이 남아 있다면 여기에서 해당 항목을 정리할 수 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionURL
    주소 창에 웹사이트의 주소를 적을 때 맨 앞에 붙는 부분이 설정되어 있다.

  • HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersion Winlogon
    파워토이를 설치했다면 여기에 로그인 암호를 지정해, 윈도우를 시동할 때 나타나는 로그인 암호 상자에 자동으로 암호가 입력되게 할 수 있다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlASD
    자동 생략 드라이버 에이전트의 내용이 기록되어 있다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlComputerName
    컴퓨터 이름이 기록되어 있다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlFileSystem
    파일 시스템에 대한 정보가 저장되어 있다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlIDConfigDB
    하드웨어 설정 초기화 파일을 구분하기 위한 ID의 집합부분이다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlInstalledFiles
    윈도우 폴더에 인스톨된 실행파일 및 가상 장치 드라이버에 대한 설정 기록.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlKeyboard Layouts
    전세계의 키보드 레이아웃 구성이 수록되어 있다. 필요한 것만 남기고 모두 삭제...

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControl
    MediaPropertiesPrivatePropertiesJoystickOEM
    조이스틱의 종류에 대한 데이터 베이스이다. 필요한것만 남기고 모두 삭제

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlMediaResourcesjoystick
    현재 시스템에 있는는 조이스틱에 대한 설정이 기록됨.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlNlsLocale
    언어 지정 장소. 영문(409)과 한글(412)를 제외한 모든 것은 삭제

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlSessionManagerCheckBadApps
    윈도우98에 치명적인 응용프로그램 리스트이다. 주로 도스용 프로그램이 주류...

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlSessionManagerCheckBadApps400
    역시 윈도우98에 치명적인 구버전의 응용프로그램 리스트이다. 윈도우3.1용과 윈도우98에 절대로 깔아서는 안되는 프로그램들 항목을 볼 수 있다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetControlUpdate
    안에 있는 UpdateMode값을 01에서 00으로 바꿔주자. 그러면 탐색기에서 파일을 리네임할 때나 복사할 때, 많은 수의 파일들을 표시할 때 속도가 증가한다. 즉 자동으로 새로고침 명령을 수행하게 된다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetServicesClass
    하드웨어 추가마법사에서 볼 수 있는 설치할 하드웨어 종류를 정의해 놓았다.

  • HKEY_LOCAL_MACHINESystemCurrentControlSetServicesVxD
    가상장치 드라이버에 대해 정의한 곳이다. 함부로 만지면 위험.

④ HKEY_USERS
컴퓨터를 공유하는 사용자 각각의 윈도우 환경에 관한 여러 가지 설정을 저장한다. 혼자 사용할 경우에는 .default 값만 있다. 대부분의 내용은 앞에서 다룬바와 같다.
⑤ HKEY_CURRENT_CONFIG
디스플레이나 프린터에 대한 설정 내용이 저장되어 있다



출처 : http://boanchanggo.tistory.com/62

:
Posted by 라면스프
원문 http://blog.naver.com/julymorning4/100035857242


'창 닫으시겠습니까' 메시지 없애는 방법(IE7에서)

부모창에서 자식창 오픈시키면서 부모창 닫을 때 '창 닫으시겠습니까' 라는 메세지 창 없이 브라우저
종료시키는 아래 스크립트가 있는데
self.opener = self;
self.close();  

이게 IE7에서 얼핏 안되게 보이지만 가능한 방법이 있습니다.

아래 내용을 참고 하세요~

[예]
//--------------------------------------
        //IE7에서 "창을 닫겠냐"는 메시지 뜨는 것 방지용
        //--------------------------------------
                function selfClose()
                {
                    if (/MSIE/.test(navigator.userAgent)) {
                        if(navigator.appVersion.indexOf("MSIE 7.0")>=0) {
                            //IE7에서는 아래와 같이
                            parent.window.open('about:blank','_self').close();
                            parent.window.opener=null;
                            parent.window.close();
                        }
                        else {
                            //IE7이 아닌 경우
                            parent.window.opener = self; 
                            parent.self.close();
                        }                       
                    } else {
                        window.name = '__t__';
                        var w = window.open('about:blank');
                        w.document.open();
                        w.document.write('<html><body><script type="text/javascript">function _(){var w=window.open("about:blank","'+window.name+'");w.close();self.close();}</'+'script></body></html>');
                        w.document.close();
                        w._();
                    }
                } 
:
Posted by 라면스프
2008. 10. 16. 17:40

EAS3.0 메모리 관련 예제 Enjoy/FLEX2008. 10. 16. 17:40

책에 나온 메모리 관련 예제입니다.

:
Posted by 라면스프