아래 블로그에 작성한 JAXB HttpClient 코드를 Spring OXM으로 수정해서 돌려보았다. 비교해볼만함

http://knight76.tistory.com/entry/JAXB-Http-Client-Example샘플

 

 

특정 URL을 호출하면 사원 정보가 나온다고 가정한다.

 

<ROOT>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

</ROOT>

 

# ROOT.java

package spring;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="ROOT")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
   
    @XmlElement(name="EMPLOYEE")
    private List<Employee> employees;

    public Root() {
        employees = new ArrayList<Employee>();
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }

}

 

# Employee.java

package test;

public class Employee {

private String id;
private String nm;

….

… // set, get

}

 

# XEmployee.java

 

public class XEmployee {

    private static List<String> employeeList;
    public static List<String> getEmployeeList() {
        return employeeList;
    }
    static {
        employeeList = new ArrayList<String>();

        employeeList.add("aaa");
         employeeList.add("bbb");
         employeeList.add("ccc");

    }
}

여기까지는 바뀌는 것이 없다.  Spring 연동 코드가 바뀌었다. 연동코드는 형광펜으로 칠해놨다.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/oxm
           http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">

    <oxm:jaxb2-marshaller id="jaxb2Marshaller">
        <oxm:class-to-be-bound name="spring.Root" />
    </oxm:jaxb2-marshaller>
   
    <!-- oxm:jaxb2-marshaller 에서 사용했던 것과 동일한 효과(예전 방식) 
    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>spring.Root</value>
            </list>
        </property>
    </bean>
    -->

    <bean id="application" class="spring.CheckEmp">
        <property name="marshaller" ref="jaxb2Marshaller" />
        <property name="unmarshaller" ref="jaxb2Marshaller" />
    </bean>

</beans>

 

main 메서드

package spring;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import javax.annotation.Resource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.transform.stream.StreamSource;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class CheckEmp {
    @Resource(name = "jaxb2Marshaller")
    Unmarshaller unmarshaller;

    @Resource(name = "jaxb2Marshaller")
    Marshaller marshaller;
   
    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }
   
    public static final boolean isSaved = false;
    public static final String URL = "http://aaaaaaaaa";
    public static JAXBContext jaxbContext;
    static {
        try {
            jaxbContext = JAXBContext
                    .newInstance(new Class[] { test.Root.class });
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

       public static void main(String[] args) throws Exception {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        CheckEmp application = (CheckEmp) appContext.getBean("application");
        application.start();
    }

    private void start() throws Exception {
        BufferedReader reader = connectURL();
        if (isSaved) {
            saveFile(reader);
        }

        Root root = getRoot(reader);

         for (String retiredEmpID : XEmployee.getEmployeeList()) {
            boolean found = false;
            for (Employee emp : root.getEmployees()) {
                if (emp.getID().trim().equalsIgnoreCase(retiredEmpID)) {
                      found = true;
                }
            }
            if (found == false) {
                System.out.println(retiredEmpID);
            }
        }
    }

    private Root getRoot(BufferedReader reader) throws Exception {
        StreamSource source = new StreamSource(reader);
        Root root = (Root) unmarshaller.unmarshal(source);
        return root;
    }

    private BufferedReader connectURL() throws IOException,
            ClientProtocolException, UnsupportedEncodingException {
        HttpGet httpget = new HttpGet(URL);
        HttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter("http.socket.timeout", 999000);

        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity == null) {
            throw new RuntimeException("url error");
        }
        InputStream instream = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                instream, "utf-8"));
        return reader;
    }

    private static void saveFile(BufferedReader reader) throws IOException {
        Writer fstream = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream("aaa.txt"), "utf-8"));
        BufferedWriter out = new BufferedWriter(fstream);
        char[] a = new char[1024];
        while (reader.read(a) > 0) {
            out.write(a);
        }
        out.flush();
        System.out.println("File created successfully.");
    }

}

 

삽질 방지를 위해서 spring debug log가 출력되게 한다.

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Threshold" value="DEBUG"/>
        <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%-5p](%F:%L) %m%n"/>
        </layout>
    </appender>
    <appender name="general" class="org.apache.log4j.ConsoleAppender">
       <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%-5p](%F:%L) %m%n"/>
       </layout>
    </appender>

    <logger name="com" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="general"/>
    </logger>

    <logger name="org.springframework" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="general"/>
    </logger>

    <root>
        <level value="WARN"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test1123</groupId>
    <artifactId>teswt1</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <spring-version>3.1.0.RELEASE</spring-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>

</project>

 

 

# 참조한 내용

Spring OXM 에 대한 자료 (Marshalling XML using O/X Mappers)

http://static.springsource.org/spring-ws/site/reference/html/oxm.html

 

 

# 기타

 

@Resource  annotation은 javax.annotation으로 플랫폼 독립적이며, jsr250에서 DI 의 리더들이 모여서 결정했다. jsr250-api.jar 를 반드시 pom.xml에 넣어야 한다.

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>

name속성에 자동으로 연결될 빈객체의 이름을 입력한다
@Resource(name="marshaller")
Marshaller marshaller;




# CheckEmp.java 코드를 Spring JUnit으로 만들기

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml"})
public class CheckEmp {

// 코드

 @Test
 public void testMarshaller() throws Exception {

 ...
}
}

Posted by '김용환'
,


나는 생각이 올바르다면 언젠가는 모든사람들에게 받아들여진다는 굳은 믿음을 가지고 있었다. 그렇기 때문에 만일 그라민 은행이 사라지는 일이 생기더라도 그 정신은 영원할 것이라고 확신한다.


이윤추구만이 자유주의의 유일한 원동력이 아니라, 사회적 목표라는 참 가치가 포함되어야 한다.


그라민 은행은 시장 경제를 옹호하고 창업을 권장하고 있다. 또한 사회적 목표(가난 퇴치, 교육 기회 제공, 여성 자립을 지원, 남녀 평등, 노년층의 복지 보장) 를 성취하고자 한다. 경제적 자유주의를 신봉하지 않는다.


사회적 책임을 다해야 할 공공기관은 관료주의 사고방식에 따른 보조금이나 정치 경제적 정책만을 남발했을 뿐 아니라, 투명성을 상실했다. 처음 시작할 때 좋은 뜻은 도중에 사라져 버렸다. 남은 것은 이윤 극대화를 지향하는 민간 부문이다. 게다가 족쇄 풀린 이윤 극대화의 사고방식이 부패와 손을 잡을 때는 가장 견고했던 사회적 연대도 쉽게 붕괴될 수 밖에 없다.


문제의 본질은 과연 경제발전이 무엇을 뜻하느냐에 달려 있다.

연대 융자는 사회로부터 버림받은 개개인에게 활동할 수 있는 힘을 주고 미래를 준비할 수 있는 토양을 제공하고 있다.

나는 전세계적으로 가난이란 사리 경제적 문제라기보다는 의지의 문제라고 언제나 생각해 왔다. 또한 가난이 오늘날까지 사라지지 않고 있는 까닭은 우리가 가난으로부터 눈을 돌리고 충분한 관심을 보이지 않기 때문이다. 가난한 사람에게 베푸는 자비심은 그들에게 아무런 도움이 되지 않는다. 자비심을 베푸는 것은 우리의 의식을 편안케 하고자 하는 이기심의 발로이다.

그들에게 똑같은 기회를 제공해주고, 우리 스스로 이들과 똑같은 무기를 들고 세상과 싸울 각오가 되어 있어야 한다는 점이다.

합당한 제도와 효과적인 조치가 동반되는 자립형 노동이야말고 실업과 가난 문제에 대항해서 싸울 수 있는 가장 좋은 방법이다.


Posted by '김용환'
,

 

apache commons의 http client와 jaxb로 어떻게 테스트할지에 대해서 작성한 글이다.

특정 URL을 호출하면 사원 정보가 나온다고 가정한다.

<ROOT>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

</ROOT>

 

객체는 Root-List<Employee>의 구조로 생각,

# Root.java 소스

package test;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "ROOT")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
   
    @XmlElement(name="EMPLOYEE")
    private List<Employee> employees;

    public Root() {
        employees = new ArrayList<Employee>();
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }

}

 

# Employee.java

package test;

public class Employee {

private String id;
private String nm;

….

… // set, get

}

 

찾고 싶은 사람의 사번을 작성한다.

# XEmployee.java

public class XEmployee {

    private static List<String> employeeList;
   
    public static List<String> getEmployeeList() {
        return employeeList;
    }
   
    static {
        employeeList = new ArrayList<String>();

        employeeList.add("aaa");
         employeeList.add("bbb");
         employeeList.add("ccc");

    }
}

 

찾고 싶은 사람을 찾아서 출력한다.

 

# main 메서드

package test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class CheckEmp {
    public static final boolean isSaved = false;
    public static final String URL = "http://xxxxxxxx";
    public static JAXBContext jaxbContext;
    static {
        try {
            jaxbContext = JAXBContext
                    .newInstance(new Class[] { test.Root.class });
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

        public static void main(String[] args) throws Exception {

        // connect url
        BufferedReader reader = connectURL();

        // save file
        if (isSaved) {
            saveFile(reader);
        }
       

        // get object
        Root root = getRoot(reader);

        // find
        for (String retiredEmpID : XEmployee.getEmployeeList()) {
            boolean found = false;
            for(Employee emp : root.getEmployees()) {
                if (emp.getID().trim().equalsIgnoreCase(retiredEmpID)) {
                    found = true;
                }
            }
            if (found == false) {
                System.out.println(retiredEmpID);
            }
        }
    }

    private static Root getRoot(BufferedReader reader) throws JAXBException {
        Root root = (Root) jaxbContext.createUnmarshaller().unmarshal(reader);
        return root;
    }

    private static BufferedReader connectURL() throws IOException,
            ClientProtocolException, UnsupportedEncodingException {

        HttpGet httpget = new HttpGet(URL);
        HttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter("http.socket.timeout", 999000);
       
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity == null) {
            throw new RuntimeException("url error");
        }
        InputStream instream = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(instream, "utf-8"));
        return reader;
    }

    private static void saveFile(BufferedReader reader) throws IOException {
        Writer fstream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("aaa.txt"), "utf-8"));
        BufferedWriter out = new BufferedWriter(fstream);
        char[] a = new char[1024] ;
        while (reader.read(a) > 0) {
            out.write(a);
        }
        out.flush();
        System.out.println("File created successfully.");
    }

}


# pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>test1123</groupId>
 <artifactId>teswt1</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <dependencies>
  <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.1.2</version>
  </dependency>
  <dependency>
   <groupId>javax.xml.bind</groupId>
   <artifactId>jaxb-api</artifactId>
   <version>2.2</version>
  </dependency>
  <dependency>
   <groupId>com.sun.xml.bind</groupId>
   <artifactId>jaxb-xjc</artifactId>
   <version>2.2</version>
  </dependency>
  <dependency>
   <groupId>com.sun.xml.bind</groupId>
   <artifactId>jaxb-impl</artifactId>
   <version>2.2</version>
  </dependency>
 </dependencies>
</project>
Posted by '김용환'
,

 

아키텍트ㅡㄹ은 프로젝트에 착수할 때 자신의 가치를 입증하려는 욕구가 있습니다. 자신의 가치를 입증하는 것이 개인의 기술적 탁월함으로 팀을 좌절시키는 쇼맨십으로 이루어져야 한다고 오해하는 아키텍트들이 있습니다.

아키텍트는 확고한 리더십으로 팀의 존경을 얻어야만 하고 기술과 팀이 운영하는 비즈니스 도메인의 이해가 있어야 합니다.

책임을 지고 다른 이들을 돌보는 청지기 정신(stewardship)은 아키텍트에게 적합한 역할입니다. 아키텍트는 그들의 고객을 위해 최선을 다해야 하며 고객의 요구를 이용하지 말아야 합니다.

시간과 노력은 회사의 자원이므로, 소트프웨어 아키텍트는 사심없는 청지기가 되어야 합니다. 최신의 따끈따끈한 프레워크나 기술 전문 유행어로 이루어진 과도하게 복잡한 시스템은 기업 지출의 희생을 담보로 하고 있습니다. 아키텍트의 활동은 투자 브로커처럼 합리적인 ROI를 창출할 수 있다는 전제 하에 고객의 돈을 사용하고 있어야 합니다.

쇼맨십을 넘는 가치 있는 청지기 정신은 여러분이 다른 사람의 돈을 사용하고 있음을 절대 잊지 않는 것입니다.

- Barry Hawkins

 

위대한 건축가는 머리가 아니라 노력과 풍요로운 마음으로 만들어진다.

- Fank Lloyd Wright

 

아키텍트들이 오늘날 가지고 있는 문제들 중 하나는 분석에 무기력한 것입니다. 이 문제를 더 크게 만드는 것은 미래에 있는 최고의 기술을 짐작하려 하는 것입니다. 그저 지금 당장 좋은 기술을 선택하는 것도 충분히 어려운 일입니다. 하물며 미래에 의미있을 것 같은 기술을 고르는 것은 헛된 일입니다.

- Richard Monson-Haefel

 

최종 사용자에게는 인터페이스가 시스템이다.

- Vinayak Hegde

Posted by '김용환'
,

일반적으로 자바 배치가 많은 경우에 cpu가 튄다. jvm 단위의

이럴 때는 여러가지를 사용하는데, 
1.  cpulimit 를 쓰는 방법
2. 서버를 여러대로 분산하는 법,
3. 웹 서버로 해서 배치를 만드는 법 (quartz 이용)
4. 스케쥴을 잘 정리할 것

자바는 기본적으로 jvm 시작시, 클래스 로딩, jvm 종료시 서버에 부하를 준다. 따라서 이 작업을 최대한 피하게 하는 것이 좋다. 따라서 10분 단위 미만의 배치는 웹 서버로 바꿔 배치를 돌리는 것이 합리적인 것 같다.
Posted by '김용환'
,

오픈캡쳐 1.4와 호환

Tool 2012. 2. 13. 15:56

오픈캡쳐 1.4  소스를 컴파일하면 나오는 바이너리를 첨부 (바이러스 없음)


Posted by '김용환'
,


1.  경험
   - 웹 서비스 또는 솔루션을 운영하면서 jvm 옵션을 변경을 다양한 경험 하기 (heap memory, gc algorithm, gc pause, logging)
   튜닝하면서 자연스럽게 인터넷에 흩어져 있는 자료들을 보면서 깊지 않은 공부 (오라클 또는 썬 문서)를 많이 본다.
   - Memory Management in the Java HotSpot™ Virtual Machine (http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf)

2. 학습 필요
   - 데니스 리치가 쓴 c programming lanuguage의 chap 8 장 (malloc, free) - 기본 중의 기본.
   - The Garbage Collection Handbook The Art of Automatic Memory Management
   - Garbage Collection: Algorithms for Automatic Dynamic Memory Management
   (운영체제와 컴파일러에 정통하신 분은 금방 보는 참고서일뿐 ......ㅡ.ㅡ;;)

3. 주화입마 될 수 있다. jdk쪽은 좀 복잡함. 머리속을 gc 를 하겠다는 생각으로 봐야함..
   - 오픈 소스 보기
      parrot (https://github.com/parrot/parrot/blob/master/src/gc/gc_gms.c)
      jdk7 (http://hg.openjdk.java.net/jdk7/modules/hotspot/file/9646293b9637/src/share/vm/gc_implementation/)
      qish (http://starynkevitch.net/Basile/qishintro.html )
      mono (http://mono-project.com/Generational_GC, https://github.com/mono/mono/tree/e4b9b8802066f6ed8cca151fe8cddcb4f3262806/mono/metadata 에서 gc.c)
      v8 (http://code.google.com/p/v8/source/browse)의 heap.cc, spaces.cc,  mark-compact.cc
     jikesrvm (http://sourceforge.net/projects/jikesrvm/files/jikesrvm/3.1.1/ )의 rvm\src\org\jikesrvm\mm\mminterface 클래스파일들
 - 논문 보기
     IEEE, ACM, 다양한 paper를 참조하고 reference를 찾아서 보기
     (http://scholar.google.co.kr/scholar?hl=ko&lr=&q=related:ppTY-k29HfoJ:scholar.google.com/&um=1&ie=UTF-8&ei=3Tw1T__XHOGTiQeW2ID2AQ&sa=X&oi=science_links&ct=sl-related&resnum=4&ved=0CF0QzwIwAw)

  
나는 다 보지는 못했고 계속 공부중..

 

Posted by '김용환'
,

 

Oracle Jdk 7부터는 G1 gc 알고리즘을 디폴트로 사용한다고 했었는데.. 인터넷에 이런 자료가 없어서 직접 테스트 해보니 디폴트는 기존의 generation model을 사용중이다. 따로 옵션을 넣어줘야 한다.

 

<서버 설치>

$ mkdir -p /home/www/jdk7

$ cd /home/www/jdk7

$ wget http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586.tar.gz

$ tar zxvf jdk-7-linux-i586.tar.gz

 


$ mkdir -p /home/www/tomcat

$ cd /home/www/tomcat

$ wget http://mirror.khlug.org/apache/tomcat/tomcat-7/v7.0.25/bin/apache-tomcat-7.0.25.zip

$ unzip apache-tomcat-7.0.25.zip

 

$ vi /home/www/.bashrc

$ export JAVA_HOME="/home/www/jdk7/jdk1.7.0"

$ source /home/www/.bashrc

 

$ cd /home/www/tomcat/apache-tomcat-7.0.25/bin

$ vi catalina.sh
(다음을 # --- 다음에 추가)
CATALINA_OPTS=" -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

* bashrc에 넣어둘 수도 있음


$ ./catalina.sh start
Using CATALINA_BASE:   /home/www/tomcat/apache-tomcat-7.0.25
Using CATALINA_HOME:   /home/www/tomcat/apache-tomcat-7.0.25
Using CATALINA_TMPDIR: /home/www/tomcat/apache-tomcat-7.0.25/temp
Using JRE_HOME:        /home/www/jdk7/jdk1.7.0
Using CLASSPATH:       /home/www/tomcat/apache-tomcat-7.0.25/bin/bootstrap.jar:/home/www/tomcat/apache-tomcat-7.0.25/bin/tomcat-juli.jar

 

$ ps -ef | grep java
www      17189     1 97 11:42 pts/1    00:00:02 /home/www/jdk7/jdk1.7.0/bin/java -Djava.util.logging.config.file=/home/www/tomcat/apache-tomcat-7.0.25/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager  -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.endorsed.dirs=/home/www/tomcat/apache-tomcat-7.0.25/endorsed -classpath /home/www/tomcat/apache-tomcat-7.0.25/bin/bootstrap.jar:/home/www/tomcat/apache-tomcat-7.0.25/bin/tomcat-juli.jar -Dcatalina.base=/home/www/tomcat/apache-tomcat-7.0.25 -Dcatalina.home=/home/www/tomcat/apache-tomcat-7.0.25 -Djava.io.tmpdir=/home/www/tomcat/apache-tomcat-7.0.25/temp org.apache.catalina.startup.Bootstrap start

 

<로컬 환경에 jdk 설치구축>

http://www.oracle.com/technetwork/java/javase/downloads/java-se-jdk-7-download-432154.html

jdk_home에 있는 bin/jconsole.exe 실행

 

<jconsole 이용>

ip와 포트을 입력해서 접속. 디폴트는 jdk 6와 동일하게 사용. 디폴트가 g1을 적용한 것이라고 했지만 young gen/old gen/perm gen 방식을 그대로 사용하는 ps marksweep, ps scavenge를 그대로 이요

 

 

G1 옵션 추가

$ vi catalina.sh
(다음을 # --- 다음에 추가)
CATALINA_OPTS=" -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false  -XX:+UseG1GC "  

 ( -XX:+UnlockExperimentalVMOptions  는 java 1.6 후반부 버전에서 G1 알고리즘을 쓸떄 사용가능하다. jdk7부터는 이 옵션없이 G1을 쓸 수 있다.)

jconsole로 확인하니, G1 Old gen, G1 young gen으로 뜨는지 확인했다.

chart상으로는 여러 영역이 보이지만, G1 자체가 young/old gen이 없기 때문에 이 정보는 나오지 않는다.








Posted by '김용환'
,

 

지금까지 jdk 6, 7에 항상 일어나는 버그이다.

String [], Byte[]와 같은  Array type ([] )으로 된 클래스를 ClassLoader를 이용해서 클래스 로딩시ClassNotFoundException이 발생한다.

그러나 Class.forName 으로 바꾸면 괜찮다. 이 문제는 reflection을 이용할 때 동일하게 나기 때문에 주의하면서 개발해야 한다.

 

jdk 6, jdk 7에서의 테스트 코드이다.

public class test {
    public static void main(String[] args) throws Exception {
        String[] s = new String[] { "aaa" };
        String clName = s.getClass().getName();
        Class c = test.class.getClassLoader().loadClass(clName);
       System.out.println(c);
    }
}

실행 결과는 다음과 같다.

Exception in thread "main" java.lang.ClassNotFoundException: [Ljava.lang.String;
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at test.main(test.java:5)

 

문제가 안 일어나게 하려면 다음과 같이 코딩해야 한다.

public class test {
    public static void main(String[] args) throws Exception {
        String[] s = new String[] { "aaa" };
        String clName = s.getClass().getName();
        Class c = Class.forName(clName,false,Thread.currentThread().getContextClassLoader());
        System.out.println(c);
    }
}

결과는 다음과 같다.

class [Ljava.lang.String;

 

이 문제는 “http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6434149”에 올라와 있다.

비슷한 이슈로 다른 버그(“http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6446627”)도 있다.

public class test {
    public static void main(String[] args) throws Exception {
        String[] objs = new String[10];
        objs[0] = new String();
        String[] objs2 = (String[]) cloneObject(objs,
                test.class.getClassLoader());
    }

    public static Object cloneObject(Object toClone,
            final ClassLoader classLoader) throws Exception {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ObjectOutputStream oOut = new ObjectOutputStream(bOut);
        oOut.writeObject(toClone);
        oOut.close();
        ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
        bOut.close();
        ObjectInputStream oIn = new ObjectInputStream(bIn) {
            protected Class resolveClass(ObjectStreamClass desc)
                    throws IOException, ClassNotFoundException {
                System.out
                        .println("Attempting to load class " + desc.getName());
                return classLoader.loadClass(desc.getName());
            }
        };
        bIn.close();
        Object copy = oIn.readObject();
        oIn.close();
        return copy;
    }

}

 

결과.

Exception in thread "main" java.lang.ClassNotFoundException: [Ljava.lang.String;
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at test.main(test.java:5)

 

이문제는 현재 많은 개발자들은 오라클이 해주기를 기다리고 있다….

오라클 버그 데이터베이스에서는 개발자들이 투표를 통해서 bug를 빨리 처리해달라는 주소도 있으니 참조할 것.
http://bugs.sun.com/bugdatabase/top25_bugs.do

 

Posted by '김용환'
,

node.js

Web service 2012. 2. 9. 16:31

 

node.js 사용만 하다가. node.js 내부에 대한 궁금증이 생겼다..

V8 + thread pool + event loop 가 핵심이다.

 

node.js 의 소스디렉토리 : https://github.com/joyent/node/

 

https://developer.palm.com/index.php?id=2109&option=com_content&view=article 에 따르면, Hp webOS 2.1에 탑재(built-in)되어 있다.

image

아키텍처는 다음과 같다. (http://blog.zenika.com/index.php?post/2011/04/10/NodeJS)

image

 

중요 라이브러리는 2가지가 있다.

1. C event loop 라이브러리 (libev) : libev - a high performance full-featured event loop written in C
(http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod)

* 이 라이브러리의 주요 특징은 Timer(ev_timer), FD(ev_io), 시그널(ev_signal), 상태(ev_stat)이 있다.

// a single header file is required
  #include <ev.h>

  #include <stdio.h> // for puts

  // every watcher type has its own typedef'd struct
  // with the name ev_TYPE
  ev_io stdin_watcher;
  ev_timer timeout_watcher;

  // all watcher callbacks have a similar signature
  // this callback is called when data is readable on stdin
  static void
  stdin_cb (EV_P_ ev_io *w, int revents)
  {
    puts ("stdin ready");
    // for one-shot events, one must manually stop the watcher
    // with its corresponding stop function.
    ev_io_stop (EV_A_ w);

    // this causes all nested ev_run's to stop iterating
    ev_break (EV_A_ EVBREAK_ALL);
  }

  // another callback, this time for a time-out
  static void
  timeout_cb (EV_P_ ev_timer *w, int revents)
  {
    puts ("timeout");
    // this causes the innermost ev_run to stop iterating
    ev_break (EV_A_ EVBREAK_ONE);
  }

  int
  main (void)
  {
    // use the default event loop unless you have special needs
    struct ev_loop *loop = EV_DEFAULT;

    // initialise an io watcher, then start it
    // this one will watch for stdin to become readable
    ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
    ev_io_start (loop, &stdin_watcher);

    // initialise a timer watcher, then start it
    // simple non-repeating 5.5 second timeout
    ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
    ev_timer_start (loop, &timeout_watcher);

    // now wait for events to arrive
    ev_run (loop, 0);

    // break was called, so exit
    return 0;
  }

 

소개 자료는 다음과 같다.

Libev is an event loop: you register interest in certain events (such as a file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events.

To do this, it must take more or less complete control over your process (or thread) by executing the event loop handler, and will then communicate events via a callback mechanism.

You register interest in certain events by registering so-called event watchers, which are relatively small C structures you initialise with the details of the event, and then hand it over to libev by starting the watcher.

 

Libev supports select, poll, the Linux-specific epoll, the BSD-specific kqueue and the Solaris-specific event port mechanisms for file descriptor events (ev_io), the Linux inotify interface (for ev_stat), Linux eventfd/signalfd (for faster and cleaner inter-thread wakeup (ev_async)/signal handling (ev_signal)) relative timers (ev_timer), absolute timers with customised rescheduling (ev_periodic), synchronous signals (ev_signal), process status change events (ev_child), and event watchers dealing with the event loop mechanism itself (ev_idle, ev_embed, ev_prepare and ev_check watchers) as well as file watchers (ev_stat) and even limited support for fork events (ev_fork).

It also is quite fast (see this benchmark comparing it to libevent for example).


2. c thread pool 라이브러리 (liibeio)

http://pod.tst.eu/http://cvs.schmorp.de/libeio/eio.pod

* async 기능 제공

예제 파일

static struct ev_loop *loop;
static ev_idle repeat_watcher;
static ev_async ready_watcher;

/* idle watcher callback, only used when eio_poll */
/* didn't handle all results in one call */
static void
repeat (EV_P_ ev_idle *w, int revents)
{
  if (eio_poll () != -1)
    ev_idle_stop (EV_A_ w);
}

/* eio has some results, process them */
static void
ready (EV_P_ ev_async *w, int revents)
{
  if (eio_poll () == -1)
    ev_idle_start (EV_A_ &repeat_watcher);
}

/* wake up the event loop */
static void
want_poll (void)
{
  ev_async_send (loop, &ready_watcher)
}

void
my_init_eio ()
{
  loop = EV_DEFAULT;

  ev_idle_init (&repeat_watcher, repeat);
  ev_async_init (&ready_watcher, ready);
  ev_async_start (loop &watcher);

  eio_init (want_poll, 0);
}

특징

This library provides fully asynchronous versions of most POSIX functions dealing with I/O. Unlike most asynchronous libraries, this not only includes read and write, but also open, stat, unlink and similar functions, as well as less rarely ones such as mknod, futime or readlink.

It also offers wrappers around sendfile (Solaris, Linux, HP-UX and FreeBSD, with emulation on other platforms) and readahead (Linux, with emulation elsewhere>).

The goal is to enable you to write fully non-blocking programs. For example, in a game server, you would not want to freeze for a few seconds just because the server is running a backup and you happen to call readdir.

 

 

3. V8 (구글 작품)

http://code.google.com/p/v8/

http://code.google.com/intl/ko-KR/apis/v8/embed.html

Posted by '김용환'
,