Spring Security 에 OAuth 2 모듈이 있는걸 알고 있지만 OAuth 로 SSO 서버를 구현해보지는 않았기에 chatGPT 에게 물어봤다


Q > Springboot 의 OAuth 를 활용해 SSO 구현 가능하니?

A > ChatGPT 는 당근 가능하다고 하며 TMI 로 아래처럼 얘기를 붙여준다

 

OAuth 정의 

OAuth는 사용자 자격 증명을 공개하지 않고 보호된 서버에서 사용자 자원에 대한 제3자 응용 프로그램의 액세스를 허용하는 인증 프레임 워크입니다. 최신 웹 애플리케이션 및 API에서 인증 및 권한 부여에 자주 사용됩니다.

Spring Boot는 웹 애플리케이션 및 API를 구축하기위한 인기있는 Java 기반 프레임 워크로서 OAuth를 지원하기 위한 다양한 도구 및 라이브러리를 제공합니다.

Spring Boot를 사용하여 OAuth를 이용한 SSO를 구현하려면 Spring Security 프레임 워크를 사용할 수 있습니다. Spring Security는 OAuth 인증 및 권한 부여를 지원하는 내장 기능을 제공합니다. Spring Security를 구성하여 Google이나 Facebook과 같은 OAuth 공급자를 신원 공급자로 사용하도록 설정할 수 있습니다.

다음은 Spring Boot를 사용하여 OAuth를 이용한 SSO를 구현하는 일반적인 단계입니다.

  1. 새로운 Spring Boot 애플리케이션을 만들거나 기존 애플리케이션을 수정하여 Spring Security를 사용합니다.
  2. Google이나 Facebook과 같은 OAuth 공급자를 선택하고 클라이언트 ID 및 클라이언트 비밀번호를 얻기 위해 공급자에 애플리케이션을 등록합니다.
  3. Spring Security를 구성하여 OAuth 공급자를 신원 공급자로 사용하도록 설정합니다.
  4. OAuth 인증 흐름을 처리하는 필요한 컨트롤러 엔드 포인트 및 사용자 인터페이스를 구현합니다.
  5. 사용자가 인증되면 세션 또는 토큰에 사용자 자격 증명을 저장하여 여러 애플리케이션에서 SSO를 활성화합니다.

Spring Boot를 사용하여 OAuth를 이용한 SSO를 구현하는 방법에 대한 자습서, 가이드 및 샘플 코드를 포함한 많은 온라인 자료가 있습니다. Spring Security 문서는 OAuth 인증 및 권한 부여를 구성하는 방법에 대한 자세한 정보를 제공하는 좋은 출발점입니다.


추가질문

이번에도 나의 질문이 조금 부족했음을 느낀다 나는 SSO Server 를 구현하는 방법을 물어보고 싶었는데, SSO 구현방법을 물어봤다.

다시 수정해서 물어보고 Springboot 기반의 Sample Code 도 달라고 요청했다

 

Q >  역시나 친절하게도 아래처럼 대답해준다 

 

First, you would need to add the necessary dependencies to your pom.xml file:

<dependencies>
    <!-- Spring Security OAuth2 dependencies -->
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>2.4.0</version>
    </dependency>
    
    <!-- Spring Boot dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.6.2</version>
    </dependency>
</dependencies>

Next, you would need to configure the OAuth2 server in your Spring Boot application. Here is an example configuration class:

@Configuration
@EnableAuthorizationServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
 
    @Autowired
    private AuthenticationManager authenticationManager;
 
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("client1")
            .secret("secret1")
            .authorizedGrantTypes("authorization_code")
            .scopes("read")
            .redirectUris("http://localhost:8081/login/oauth2/code/client1")
            .and()
            .withClient("client2")
            .secret("secret2")
            .authorizedGrantTypes("authorization_code")
            .scopes("read")
            .redirectUris("http://localhost:8082/login/oauth2/code/client2");
    }
 
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
 
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");
    }
}

In this example configuration class, we are configuring two clients ("client1" and "client2") with different credentials and redirect URIs. We are also specifying that the clients are authorized to use the "authorization_code" grant type with the "read" scope. Finally, we are specifying that the AuthenticationManager should be used to authenticate clients and users.

You would also need to configure your Spring Boot application to use Spring Security for authentication. Here is an example WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/oauth/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user1")
            .password("{noop}password1")
            .roles("USER")
            .and()
            .withUser("user2")
            .password("{noop}password2")
            .roles("USER");
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

In this example WebSecurityConfigurerAdapter, we are configuring Spring Security to permit all requests to the "/oauth" endpoint and to require authentication for all other requests. We are also configuring an in-memory UserDetailsService with two users and their passwords,

 

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

Servlet 2.1 부터 HttpSession 의 getSessionContext() 메소드가 Deprecate 되었다.
저렇게 가져온 HttpSessionContext 에서 getSession(id) 해버리면 끝났던 것이, 이제는 직접 Map 을 만들던가 하여
getSession(id) 를 구현해 주어야 하는 불편함이 생겼다.

아래 코드 처럼, HttpSessionListener 를 implement 하여 Session 이 생성되거나 사라질 때 마다 Map 에 넣어서 관리를 해주도록 코딩을 해야 한다. 나중에 현재 접속중인 사용자와 같은 기능을 할때에도 아래를 응용하여 잘 쓰면 된다.
   
     17 public class SessionListener implements HttpSessionListener{
     18
     19     public void init(ServletConfig config){
     20     }
     21
     22     /**
     23      * Adds sessions to the context scoped HashMap when they begin.
     24      */
     25     public void sessionCreated(HttpSessionEvent event){
     26         HttpSession    session     = event.getSession();
     27         ServletContext context     = session.getServletContext();
     28         Map            activeUsers = (Map)context.getAttribute("activeUsers");
     29
     30         activeUsers.put(session.getId(), session);
     31     }
     32
     33     /**
     34      * Removes sessions from the context scoped HashMap when they expire
     35      * or are invalidated.
     36      */
     37     public void sessionDestroyed(HttpSessionEvent event){
     38         HttpSession    session     = event.getSession();
     39         ServletContext context     = session.getServletContext();
     40         Map            activeUsers = (Map)context.getAttribute("activeUsers");
     41
     42         activeUsers.remove(session.getId());
     43     }
     44 }

직접 Java 코드에서 request.getSession(true); 했을 때, Listener 가 잘 Call 되지 않는다라는 글도 있었는데, 이점을 잘 테스트 하며 사용해보도록 한다.

그리고, Clustered 환경에서 혹시나 문제 소지가 있을 수도 있으니, 테스트 해가면서 사용한다.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,


--------------------------------------------------------------
request.getRequestedSessionId()는 지금 만들어진 세션Id을 보기 위함이 아니라,
이전에 만들어진세션의 Id를 보기 위함입니다
--------------------------------------------------------------
세션은 보통 세션만 쓰지는 않습니다. 요것이 life타임이 얻는것이나 셋팅하는 값으로 잘 안되기 때문입니다.
디폴트가 30분인데 30분이 되기 전에 사라지는 일이 종종발생하기 때문입니다.
세션에 대한 메소드를 추가 해서 소스를 올렸습니다.
getCreateTime : 생성된 시간을 반환해주는 메소드입니다.
getLastAccessedTime : 마지막으로 세션을 access한 시간을 반환해줍니다.
getMaxInactiveInterval  : 마지막 acceess로 부터 살아남을 수 있는 시간입니다.
하지만 전 그전에 사라지는 경우를 종종 봐왔기때문에 오히려 살아남을 수 있는 최대한의 시간이라고 말하고 싶습니다.
getId : 서버가 클라이언트별루 주는 세션ID입니다. 인식자인 셈이죠..


아래 소스를 실행하면 아이디를 넣어 달라는 말이 나올겁니다. 거기서 아이디를 넣으면 그 아이디를 세션에 넣습니다.
그리고는 소스 하단부분의 if문장을 실행하게 되죠.


 


<%@ page contentType="text/html; charset=euc-kr"   session="true" %>
<%@ page import="java.io.*,java.util.*"%>
<html>
<body>
<%
if(session.getValue("id") == null  ){
%>
  아이디를 입력하세요.<br>
  아이디가 없으신 분은 guest를 입력하세요.<br>
  <form  >
      아이디 <input type="text" name="id"><br>
              <input type="submit" value="login">
  </form>           
<%
}
%>


<%
String user="";
if(request.getParameter("id") != null){
  user=request.getParameter("id");
  session.putValue("id",user);
          java.util.Enumeration st = session.getAttributeNames();
%>
  <br>
  <table border="1" align="center">
              <tr>
                          <td>getCreationTime()</td>
                          <td><%=(new Date(session.getCreationTime()))%></td>
              </tr>
              <tr>
                          <td>getID</td>
                          <td><%=session.getId()%></td>
              </tr>
              <tr>
                          <td>getMaxInactiveInterval</td>
                          <td><%=(session.getMaxInactiveInterval()/60)%>min</td>
              <tr>
              <tr>
                          <td>getLastAccessedTime()</td>
                          <td><%=(new Date(session.getLastAccessedTime()))%></td>
              </tr>
  </table>


<%
}
%>
</body>
</html>


--------------------------------------------------------------
일정한 시간이 지나서, 이미 해당 HttpSession 이 invalidate 되었군요...
이미 invalidate 된 session을 다시 invalidate 시키려고 하면 IllegalStateException이
발생합니다. 이 경우에 발생하는 IllegalStateException은 무시하시면 되겠습니다.


아래처럼 고치세요..


>    String mem_id = req.getParameter("mem_id");
>    HttpSession session = SessionPool.get(mem_id);
>
>    if(session!=null) {
>       session.invalidate(); // <--- !!!
>       SessionPool.remove(mem_id);
>    }


==>


>    String mem_id = req.getParameter("mem_id");
>    HttpSession session = SessionPool.get(mem_id);
>
>    if(session!=null) {
>       try{session.invalidate();}catch(Exception e){} // <-- !!!
>       SessionPool.remove(mem_id);
>    }
--------------------------------------------------------------


1. 현재 로긴되어 있는 사용자들의 id 와 세션카운트를 하는 방법


 


package session;


import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Enumeration;


public class SessionDisplay extends HttpServlet {


 public void doGet(HttpServletRequest req, HttpServletResponse res)
 throws ServletException, IOException {


  res.setContentType("text/plain");
  PrintWriter out = res.getWriter();


  HttpSession dummySession = req.getSession(true);
  dummySession.putValue("userID", "Watcher");
  HttpSessionContext context = dummySession.getSessionContext();


  int i = 0;
  Enumeration ids = context.getIds();
  out.println("========================================");   
  out.println("No  SessionID  UserID");   
  out.println("========================================");   
  while (ids.hasMoreElements()) {
   i++;
   String id = (String) ids.nextElement();
   HttpSession session = context.getSession(id);
   String user_id = (String)session.getValue("userID");
   out.print("(" + i + ")" + id );
   out.println("  userID = [" + user_id + "]");   
  }
  out.println("========================================");   
  out.println("Total Connect User : " + i );
  out.println("========================================");   
  out.flush();
 }
}
--------------------------------------------------------------


1. user들이 로그인시 각각의 session에 아이디등이 저장됩니다.
    관리자입장에서 모든 유저들의 로그인상태를 알고자 하는데요,
    모든 유저들의 session에 저장된 값을 읽을수 있는지요...


 


   int k = 0;
   int j = 0;
   HttpSessionContext context = session.getSessionContext();
   Enumeration ids = context.getIds();
   while(ids.hasMoreElements())
   {
      String id = (String) ids.nextElement();
      out.println("<tr><td>");
      out.println(id);
      HttpSession foreignSession = context.getSession(id);
      String foreignUser = (String) foreignSession.getValue("LoginUser");
      String foreignName = (String) foreignSession.getValue("LoginUserName");
      out.println("<td>"+foreignUser);
      out.println("<td>"+foreignName);
      out.println("<td>"+request.getHeader("REMOTE_ADDR"));
      out.println("<td>"+new Date(foreignSession.getCreationTime()));
      out.println("<td>"+new Date(foreignSession.getLastAccessedTime()));
      out.println("</tr>");
   }
  
   위와 같이 하였더니 되더군요...
   근데요 브라우저 기준 세션을 보여주더군요...
   세션이 null로 나온것은 세션저장안된 브라우저랍니다. 
--------------------------------------------------------------


1. 세션 ID획득하는 방법임다.
  
   // 이건 세션의 컨텍스트를 얻기위한겁니다..(컨텍스터를 이용해서 세션의 ID를 알려고...)
   HttpSessionContext context = session.getSessionContext();
  
   // 위의 컨텍스트를 이용해서...
   Enumeration ids = context.getIds();
  
   // 최신의 상태가 아닌 세션을 검색하기위해 세션ID를 살펴봄..
   while (ids.hasMoreElements()) {
      String id = (String)ids.nextElement();
      out.println("Checking " + id + "...."); // 세션의 ID가 나오겠죠...
      HttpSession session = context.getSession(id);
      . . .
      String foreignUser = (String)foreignSession.getValue("user_id");
   }
--------------------------------------------------------------


1. jsp에서 회원로그인에서 session을 받아 처리하는 부분하고 이 session을 가지고
   정보수정이랑 하고 싶은데 어떻게 처리를 해 줘야 하나요?
  
   로그인할때 회원아이디값을 넘겨줍니다.
   값을 받은 페이지에서는 그 값을 세션에 넣습니다.
   이렇게요..
   session.putValue("id",userid);
   여기서 userid는 회원아이디값을 받은 String입니다.
   그러면 세션에 id가 들어가겠지요.
   다음으로 정보수정하는 페이지에 세션을 가져오는 문장을 넣지요.
   session.getValue("id");
   그리고 그 값을 String형으로 변환해서 임의의 변수에 넣습니다.
   그리고 그 임의의 변수를 이용해서 해당회원의 정보를 수정하면 되겠지요...
--------------------------------------------------------------


1. >client별 세션객체를 얻어서 client들의 세션 저장내용을 지우는 부분입니다...
   >근데 맨날도 아니구 가끔 아주 가끔 foreignSession객체에서 NullPointerException이
   >발생하는데요... 왜 그런에러가 나는지 모르겠네요...


   > HttpSessionContext context = session.getSessionContext();
   > Enumeration ids = context.getIds();
   > while(ids.hasMoreElements())
   > {
   > id = (String) ids.nextElement();
   > HttpSession foreignSession = context.getSession(id);
   > String[] session_valuenames = foreignSession.getValueNames();
   > for(int i=0; i<session_valuenames.length; i++)
   > {
   > foreignSession.removeValue(session_valuenames[i]);
   > }
   > }
  
   일종의..동기화 문제로 보여집니다.
   세션목록을 가져온 후,
   그리고 세션저장내용을 지우기 전에
   세션타임아웃 등의 이유로 세션이 없어지면
   해당 id값이 없으니 null이 들어갈것이구..
   모 일단 그렇게 보여지네요 ^^



또한 참고하세요..


 


☞ 로그인하고 로그아웃할때 데이터베이스 테이블에 값을 설정해서 비교하는 방법이 있습니다.


☞ 세션정보에 로그인한 사용자의 데이터도 넣을수 있을수 있다면,
세션을 체크해서 주기적으로 데이터베이스를 체크한다면 가능할거 같기두 한데요...


☞ javax.servlet.http.* 패키지에 보면 HttpSessionBindingListener 인터페이스가 있습니다.


이 인터페이스에는 몇개의 메소드가 있는데 그 중 한개가 아래에 있는것입니다.


 


// HttpSessionBindingListener 구현
public void valueUnbound(HttpSessionBindingEvent http) {
        logout();
}


 


위 메소드는 서블릿에서 사용자의 세션이 끊어졌을때 생기는 이벤트입니다.
그러니깐 사용자가 로그인 했을때 데이타 베이스에 세션 정보가 있다면 중복 로그인한 사용자이고, 없다면 세션 정보를 넣어두고, 위 메소드에서 세션 종료시 DB에 저장된 세션정보를 지우던지 필드를 ™V팅하던지 작업을 하시면 될것같습니다.


 


? 관련 메소드 정리


Object getAttribute(String name)
 - 주어진 이름으로 세션에 저장된 객체를 리턴한다. ※ Object getValue(String name)


Enumeration getAttributeNames()
 - 세션에 저장된 모든 객체들의 이름을 Enumeration 타입으로 리턴한다. ※ String


 


getValueNames()
long getCreationTime()
 - 1970년 1월 1일 0시 0분 0초를 기준으로 세션이 생성된 시간을 리턴한다.(단위 ms)


String getId()
 - 세션의 ID를 리턴한다.


long getLastAccessedTime()
 - 1970년 1월 1일 0시 0분 0초를 기준으로 클라이언트가 이 세션에서 요청을 보낸 마지막 시간을 리턴한다.


int getMaxInactiveInterval()
 - 서버가 클라이언트의 요청없이 세션을 유지하는 최대 시간을 리턴한다. (단위 초)


void invalidate()
 - 세션을 종료한다.


boolean isNew()
 - 세션이 만들어지고 클라이언트가 아직 세션에 조인되지 않았으면 true를 리턴한다.


void setAttribute(String name, Object value)
 - 세션에 이름을 이용해서 객체를 저장시킨다. ※ void putValue(String name, Object value)


void removeAttribute(String name)
 - 주어진 이름의 객체를 세션에서 삭제한다. ※ void removeValue(String name)


void setMaxInactiveInterval(int interval)
 - 클라이언트의 요청없이 세션을 유지할 수 있는 최대 시간을 설정한다. (단위 초)

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

<Iplanet 홈>/https-admserv/config/admpwd 파일을 열어보면
admin 의 ID 와 Password (SHA 인코딩된) 가 있음.

뒤의 Password 를 지워버리고, 다시 로그인 하면 됨.
로그인 할때, Password 는 비워놓고 하도록 함.

그리고 나서 패스워드 바꾸자.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

Java 2 에서 부터 (1.3)는, Delegation Model 을 사용한다.

1. Class 가 이미 로드되어있는지 체크
2. Parent 의 Class Loader 에게 Class Load 하도록 위임함
3. 2 과정을 반복하며 최상위 Class Loader 까지 간다
4. 더이상 부모 ClassLoader 가 없으면, BootStrapClassLoader() 에게 요청한다
5. BootStrap 부터 다시 차근히 내려오면서 Class 로딩을 한다.
6. 클래스가 로드 되면 해당 클래스를 리턴한다
7. 이상이 ClassLoader.loadClass() 메커니즘이고, 만약 parent 에서 못찾으면,
    자신의 findClass() method 를 call 해서 클래스를 찾는다

Custom ClassLoader 를 생성할 때, 생성자에 parent classloader 를 지정할 수 있게 되어있음
만약 지정하지 않으면, 기본적으로 getSystemClassLoader() 를 통해, SystemClassLoader 를
parent 로 지정함. 이 system class loader 는 현재 invoking thread 의 context class loader 로 설정된다

* BootStrap 클래스로더 : Java Runtime Library 에 있는 클래스를 로딩하는 역할을 맡고 있음. 클래스로더 체인의
가장 첫번째임. 기본적으로 rt.jar 에 있는 클래스를 Bootstrap ClassLoader 가 로드 한다.

* 하나의 JVM 에 여러 클래스로더가 각각 같은 Package.Class 를 Load 하면, 각각의 인스턴스가 따로 생긴다.
결국, Java 에서의 클래스 생성은 "패키지, 클래스, 클래스로더" 의 3가지의 조합으로 구분되는 것이다

* Java2 의 표준 Runtime Library (jre/lib/rt.jar) 는 공개/내부사용 클래스 로더들이 있다
  - java.net.URLClassLoader
   파일, HTTP, FTP 등을 사용하여 Class 를 Load 할 수 있는 ClassLoader 임

  import java.net.URL;
  import java.net.URLClassLoader;
  
  public class FileSystemTest {
  
   public static void main(String[] args) throws Exception {
   URL[] urls = { new java.io.File("/usr/classes").toURL(); }
  
   URLClassLoader ucl = new URLClassLoader(urls);
   
   Class kalss = ucl.loadClass("javacan.exam.HelloWorld");
   Object obj = klass.newInstance();
   // obj를 사용하여 적절한 것을 한다.
   }
  }

  - BootStrap 클래스로더
   엄밀히 말해 Java 클래스로더가 아니고, 네이티브 로더로, Object 와 같은 코어 자바클래스를 VM 에 로딩할때 사용된다. sun.boot.class.path 프로퍼티에 정의 된 값을 사용하여 자바 런타임 라이브러리를 찾는다. 만약 명시적으로 지정하지 않으면 <JDK>/jre/lib/rt.jar 로 부터 런타임 클래스들을 로딩한다.
  JDK 1.0 이나 1.1.X 대는 CLASSPATH 나 -classpath 에 런타임을 추가해줬어야 하지만, Java2 부터는 BootStrap 클래스로더가 런타임라이브러리를 자동으로 로드해주므로 지정 할 필요가 없다.

  - sun.misc.Launcher$ExtClassLoader
   자바의 확장클래스를 로드할 때 사용한다. ExtClassLoader 는 URLClassLoader 를 상속하며, java.ext.dirs 프로퍼티에 지정한 디렉토리에 위치한 .jar 들로 부터 클래스를 읽어온다. 명시하지 않으면 기본적으로 <JDK>/jre/lib/ext 디렉토리에 있는 .jar 들을 읽어서 클래스를 로드한다

  - sun.misc.Launcher$AppClassLoader
   시스템 또는 어플리케이션 클래스로더라고 불린다. java.class.path 프로퍼티에 명시된 경로에서 코드를 로딩하는 클래스로더이다. URLClassLoader 를 상속한다. CLASSPATH 에 있는 디렉토리나 .jar 파일들은 모두 URL 로 변환되어 AppClassLoader 에게 전달된다.

   ClassLoader.getSystemClassLoader() 를 호출하면 이 클래스가 리턴된다. 개발자가 작성한 대부분의 클래스는 이 클래스로더를 통해 로드된다. AppClassLoader 는 부모 ClassLoader 로 ExtClassLoader 를 지정하고 있으므로, ext 디렉토리에 있는 jar 파일로 부터 클래스들을 로드할 수 있다.

  - sun.applet.AppletClassLoader
  
브라우저가 Applet 의 바이트코드를 다운로드 하고, 그 애플릿을 실행하기 위한 클래스를 로드하는 Class Loader 이다. URLClassLoader 를 상속받고 있어서, HTTP 나 FTP 등을 통해 클래스를 로드 가능 한 것이다. 그러나 IE 나 각 브라우저 별로, 애플릿 클래스로더를 구현하고 있는 경우가 있어, 브라우져 별로 동작이 다를 수 있다.

  - java.security.SecureClassLoader
   JVM 에 바이트코드를 로딩하고 사용하는데에 관한 보안을 제어하는 추상클래스로, URLClassLoader 를 포함한 ClassLoader 가 상속받아서 사용하는 추상클래스이다.

  - java.rmi.server.RMIClassLoader
   ClassLoader 가 아니며, RMI 런타임에서 클래스의 로딩과 마샬링을 처리해주는 래퍼클래스이다. 실제로sun.rmi.serer.LoaderHandler 와의 간단한 브릿지 역할을 하는 클래스이다. 실제 클래스 로딩은 LoaderHandler 의 Inner 클래스가 담당하게 된다. 이때 이 inner 클래스들은 URLClassLoader 를 상속받아 구현되어 있다.

* Custom ClassLoader 는 findClass(String) 를 구현하여 자신만의 클래스 로딩에만 신경쓰면 되며, 나머지는 parent 로 올리면 된다.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

보통은 저런 경우는 안생기지만, 하나의 WAS 에서, Context 가 다른 두개의 웹어플리케이션에서 각각 JNI 호출을 통해, 같은 DLL 을 사용하려는 경우 발생한 적이 있다.

이때는, 해당 JNI Java 라이브러리(.jar)나 클래스를 WAR Class Loader 가 아닌, System Class Loader 가 로드할 수 있게, System Class Path 에 두어 사용해야 한다.

웹로직의 경우, 해당 jar 를 Domain 밑의 lib 이나 server 의 lib 에 두고서 사용하면 된다.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,


1. java 로 DLL 의 프로토타입 생성

package jnitest.loader;

public class JNILoader {
 public native void greet();
 
 /*
 static {
  System.loadLibrary("HardInfo");
 }
 */
 
 public void loadLibrary() {
  System.loadLibrary("HardInfo");
 }
}

2. javah -jni <위 1번의 class 이름> 해서, C 언어용 헤더파일 생성

3. 위 헤더파일을 CPP 에서 include 하고, JDK 의 include 디렉토리를 Include Path 로 잡아서
cpp 컴파일 진행

4, 만들어진 DLL 이나 so 를 적정 디렉토리에 위치함

5. -Djava.library.path=<dll 패스> 하여 추가하더나, PATH 에 해당 디렉토리 잡히거나, Windows 디렉토리에 넣는다

6. 위 1 예제의 객체를 생성하고, 위의 경우, loadLibrary() 호출하고 (아니면 아예 static{ } 블록에서 System.loadLibrary 사용) JNI 를 사용한다

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

개요

Java Platform에서의 Stack추적은, 개발자 관리/운영자로 하여금, JVM Thread Monitor 대한 확실한 정보를 분석할 있는 수단으로 이용되고 있다.

문서에서는, major vendor 3개의 JVM 대하여 Thread State 중심으로, 차이점을

예제와 함께 다뤄보고자 한다.

(, JEUS 같이 Web Application Server 운영되는 JVM 대한 Dump Stack분석을 주로 설명할 것이다.)

 
환경

OS

Version

JDK Version

JEUS

SunOS

5.10 (64bit)

1.5.0_14

6.0

HP-UX

11.23 (64bit)

1.5.0.11

6.0

AIX

5.3 (64bit)

J2RE 1.5.0 SR6b / J2RE 1.4.2 SR5

6.0

 
Thread State

JVM Thread Dump상에서, 다시 말해 WAS등의 Multi Threading환경에서의 Thread Dump 정보에서, 각각의 Thread들은 다양한 상태(State)’ 가지고 있다.

물론, JVM 버전이라 던지, 내부적인 알고리즘에 의하여, 모든 플랫폼에 대하여 공통적으로 동일하게 나타나지는 않지만, 고유의 상태표시법을 가지고 있다.

 

아래는, 표준 JVM이라 있는 Sun JDK Thread State 분류이다.
(
이는, HP-UX / Linux / Windows 플랫폼에서 거의 같은 형식일 것이다.)

State

의미

R

Running or runnable thread

S

Suspended thread

CW

Thread waiting on a condition variable

MW

Thread waiting on a monitor lock

MS

Thread suspended waiting on a monitor lock

 

AIX JDK 경우, 크게 아래와 같은 분류를 가진다. (주의 : JDK버전에 따라 차이가 있을 있음)

보면 있듯이, 크게 ‘Thread 실행중 인지 아닌지 관점에서 분류되었다.

(* the thread is currently runnable or not)

State

의미

R

The thread is runnable

CW

Conditioned wait

MW

MUxSemWait

 

그러나, 아래 예제에서도 있겠지만, Vendor JDK 버전에 따라서 Thread State 상당히 차이를 보이는 점을 있을 것이다. 차이점을 비교해 보는 것을 중심으로 예제를 진행한다.

 

Thread Dump 생성

JVM Thread Stack 추적하는 방법에는 크게 3가지가 있는데, 여기서는 첫번째 방법인 외부Signal 형식을 살펴볼 것이다.

JVM에는 Signal Handler 내장되어 있으며, 특히 외부로부터 특정 QUIT 받았을 경우,

당시의 Thread, Monitor 정보를 재귀적으로 남기도록 프로그래밍 되어 있다.

형식) kill –Quit PID
        -.
여기서 PID Thread Dump 남기고자 하는 Process PID이다
.
           JEUS
경우, 일반적으로 Container 프로세스의 PID 사용한다.

) kill -3 1234

여기서 말하는 Quit 시그널은, 통상적으로 ANSI, POSIX 거의 모든 계열에서 ‘3’ 의미한다.

참고로, 플랫폼이 제공하는 Signal Table ‘kill –l’ 명령으로 조회해볼 있다.

Thread State 예제

Thread 상태 예제를, Sun JDK 기준으로 살펴보고, 기타 플랫폼도 같이 알아보도록 한다.

살펴볼 Thread 상태는 아래와 같다.

l          Running Monitor Wait

l          Condition Wait

그리고, 추가적으로 multi-threading 환경에서 문제가 있는 아래의 상황도 살펴볼 것이다.

l          Dead Lock

Running / Monitor Wait 상태

모든 객체는 Monitor 가지고 있고, 동기화가 필요한 경우 Thread 해당 Monitor Lock 있다. multi-threading 환경에서 경우, Monitor 선점한 Thread 동기화 블록을 벗어나기 전까지, Locked 객체를 사용하고자 하는 다른 Thread들은 동기화가 시작되는 부분에서 (Monitor cache lock)’ 들어가고, 상태가 MW(Monitor wait) 변하게 된다.

 


[사용된 코드 : thread-mw.jsp]

코드 설명 : 첫번째 Thread 동기화 블록에서, object 객체에 대한 Lock 걸고, 블록 안으로 들어가서, 일정기간 대기하게 된다( 15). 첫번째 Thread 동기화 블록을 빠져 나오기 전에, 두번째, 세번째 Thread 수행시키면, Thread object객체에 대한 Monitor 기다리면서, Monitor cache 들어가게 된다.

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>thread-mw.jsp</title>

</head>

<body>

<%!

        public static Object object = new Object();

%>

<%

        synchronized (object) {

                for (long i = 0; i < 10000000000L; i++) {

                }

                out.println("-- Finish --");

        }

%>

</body>

</html>

 

[SunOS]

l          Thread 실행 순서 : w2 à w1 à w0

l          Dump 내용

"http1-w2 [container1-15]" prio=10 tid=0x000000010140f2c0 nid=0x3b runnable [0xffffffff578fe000..0xffffffff578ff92
8]     at jeus_jspwork._600_thead_5fmw_5fjsp._jspService(_600_thead_5fmw_5fjsp.java:65)
        - waiting to lock <0xffffffff7238ca98> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w0 [container1-13]" prio=10 tid=0x0000000101196f40 nid=0x39 waiting for monitor entry [0xffffffff57cfe000..
0xffffffff57cff828]
        at jeus_jspwork._600_thead_5fmw_5fjsp._jspService(_600_thead_5fmw_5fjsp.java:65)
        - waiting to lock <0xffffffff7238ca98> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w1 [container1-16]" prio=10 tid=0x0000000100aa7680 nid=0x3a waiting for monitor entry [0xffffffff57afe000..
0xffffffff57aff8a8]
        at jeus_jspwork._600_thead_5fmw_5fjsp._jspService(_600_thead_5fmw_5fjsp.java:64)
        - waiting to lock <0xffffffff7238ca98> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : w2 Thread 동기화 블럭에 진입하여 for문을 수행중이기 때문에, ‘runnable’으로 표시되고, w1 w0 Thread 동기화 블록 진입을 위하여, object 객체의 Lock 해제되기를 기다리면서, Monitor cache 들어가고 ‘waiting for monitor entry’ 표시된다.

 

 

[HP-UX]

l          Thread 실행 순서 : w2 à w0 à w1

l          Dump 내용

"http1-w2 [container1-15]" prio=10 tid=60000000024ffc40 nid=60 lwp_id=1583373 runnable [9fffffff786ff000..9fffffff
78700a40]
        at jeus_jspwork._600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:65)
        - waiting to lock <9fffffffb87909d0> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w1 [container1-16]" prio=10 tid=60000000024bc480 nid=59 lwp_id=1583372 waiting for monitor entry [9fffffff7
8900000..9fffffff78900ac0]
        at jeus_jspwork._600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:64)
        - waiting to lock <9fffffffb87909d0> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w0 [container1-13]" prio=10 tid=60000000024b6180 nid=58 lwp_id=1583371 waiting for monitor entry [9fffffff7
8b00000..9fffffff78b00d40]
        at jeus_jspwork._600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:64)
        - waiting to lock <9fffffffb87909d0> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 동기화 블록 진입 순서대로, w2 ‘runnable’으로 표시되고, w0 w1 Thread ‘waiting for monitor entry’ 표시된다. 이는 SunOS 플랫폼에서와 마찬가지로 HotSpot계열의 JVM 사용하기 때문에 매우 유사하다.

 

[AIX / JDK 1.5]

l          Thread 실행 순서 : w2 à w1 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w0" (TID:0x0000000114948E00, sys_thread_t:0x00000001146DE4D0, state:B, native ID:0x00000000000D00E7) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:63(Compiled Code))
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/engine/ServletWrapper.execute(ServletWrapper.java:220)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.execute(JspServletWrapper.java:139)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w1" (TID:0x0000000114A91900, sys_thread_t:0x00000001149E9F70, state:B, native ID:0x00000000001AA06F) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:63)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/engine/ServletWrapper.execute(ServletWrapper.java:220)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.execute(JspServletWrapper.java:139)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w2" (TID:0x0000000114CC6000, sys_thread_t:0x00000001149EA450, state:CW, native ID:0x00000000001460CB) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fmw_5fjsp._jspService(_600_thread_5fmw_5fjsp.java:64)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/servlets/JspServlet.execute(JspServlet.java:359)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 첫번째 Thread w2 동기화 블록 진입 ‘state:CW’상태가 되었고, w1 w0 Monitor 대한 Lock 기다리면서 ‘state:B’ 변하는 것을 있다.

 

[AIX / JDK 1.4]

l          Thread 실행 순서 : w1 à w2 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w2" (TID:0x3031E040, sys_thread_t:0x387295A8, state:CW, native ID:0x393C) prio=5
4XESTACKTRACE          at jeus_jspwork._500_thread_5fmw_5fjsp._jspService(_500_thread_5fmw_5fjsp.java(Compiled Code))
4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)
4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:213)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:140)
4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)
3XHNATIVESTACK       Native Stack
NULL                 ------------
3XHSTACKLINE         at 0x38EC9E24 in
3XHSTACKLINE         at 0xD012316C in _event_wait
3XHSTACKLINE         at 0xD012E9DC in _cond_wait_local
3XHSTACKLINE         at 0xD012EEB0 in _cond_wait
3XHSTACKLINE         at 0xD012F874 in pthread_cond_timedwait
3XHSTACKLINE         at 0xD22A6A10 in condvarTimedWaitUpTo248Days
3XHSTACKLINE         at 0xD22A6BA0 in condvarTimedWait
3XHSTACKLINE         at 0xD22A5988 in sysMonitorWait
3XHSTACKLINE         at 0xD21604F4 in lkMonitorEnter
3XHSTACKLINE         at 0xD2318F08 in _jit_monitorEnterQuicker
3XHSTACKLINE         at 0xD2509220 in JITSigSegvHandler
3XHSTACKLINE         at 0x353396E4 in
3XHSTACKLINE         at 0x353396E4 in
3XMTHREADINFO      "http1-w1" (TID:0x3031E150, sys_thread_t:0x38726F28, state:R, native ID:0x383B) prio=5
4XESTACKTRACE          at jeus_jspwork._500_thread_5fmw_5fjsp._jspService(_500_thread_5fmw_5fjsp.java(Compiled Code))
4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)
4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)
3XHNATIVESTACK       Native Stack
NULL                 ------------
3XHSTACKLINE         at 0x38E45390 in
3XMTHREADINFO      "http1-w0 [container1-13]" (TID:0x3031BDD0, sys_thread_t:0x38726928, state:CW, native ID:0x373A) prio=5
4XESTACKTRACE          at jeus_jspwork._500_thread_5fmw_5fjsp._jspService(_500_thread_5fmw_5fjsp.java(Compiled Code))
4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)
4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:213)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:140)
4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)
3XHNATIVESTACK       Native Stack
NULL                 ------------
3XHSTACKLINE         at 0x38D43804 in
3XHSTACKLINE         at 0xD012316C in _event_wait
3XHSTACKLINE         at 0xD012E9DC in _cond_wait_local
3XHSTACKLINE         at 0xD012EEB0 in _cond_wait
3XHSTACKLINE         at 0xD012F874 in pthread_cond_timedwait
3XHSTACKLINE         at 0xD22A6A10 in condvarTimedWaitUpTo248Days
3XHSTACKLINE         at 0xD22A6BA0 in condvarTimedWait
3XHSTACKLINE         at 0xD22A5988 in sysMonitorWait
3XHSTACKLINE         at 0xD21604F4 in lkMonitorEnter
3XHSTACKLINE         at 0xD2318F08 in _jit_monitorEnterQuicker
3XHSTACKLINE         at 0xD2509220 in JITSigSegvHandler
3XHSTACKLINE         at 0x353396E4 in
3XHSTACKLINE         at 0x353396E4 in

결과 설명 : 첫번째 Thread w1 동기화 블록 진입 ‘state:R’상태가 되었고, w2 w0 Monitor 대한 Lock 기다리면서, ‘state:CW’ 변하였다.


Condition Wait 상태

조건대기상태로도 표현되는 CW, 흔히 Thread 동기화 블록 안에 있거나, 혹은 Thread.sleep, object.wait()상태에 머물면서 event 기다리는 상황에서 감지가 된다.

여기서 주의할 점은, wait()상태에 머물던 Thread notify계열의 event 전달 받았다고 해도,

다른 Thread들은, Thread 동기화 블록을 떠나기 전까지는, 객체 Monitor Lock 획득 없다는 점이다.

 

[사용된 코드 : thread-cw.jsp]

코드설명 : 첫번째 Thread if조건에 의해, object 객체에 Lock 걸음과 동시에, 동기화 블록에 진입하게 되고, wait상태로 빠지게 되며, 이벤트를 대기하는 상태가 된다. 그와 동시에 동기화 블록에 대한 Lock 해제되게 된다. 이후 두번째 Thread역시 if조건에 의해 동기화 블록에 진입하고, object객체가 깨어나기를 대기하고 있는 상태가 된다. 세번째 Thread else루틴을 지나, finally절에 진입하고, 15 이후 object 객체에 대해 notifyAll() 이벤트를 전송한다.

<%@ page language="java" contentType="text/html; charset=EUC-KR"

        pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTL 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>thread-cw.jsp</title>

</head>

<body>

<%!

        public static Object object = new Object();

        public static int count = 0;

%>

<%

        try {

                if (count <= 1) {

                        synchronized (object) {

                        count++;

                        object.wait(100000);

                        }

                } else {

                }

        } catch (Exception e) {

                e.printStackTrace();

        } finally {

                for (long i = 0; i < 10000000000L; i++) {

                }

                object.notifyAll();

                out.println("-- Finish --");

        }

%>

</body>

</html>

 

 

[SunOS]

l          Thread 실행 순서 : w0 à w1 à w2

l          Dump 내용

"http1-w2" prio=10 tid=0x000000010140f2c0 nid=0x3b runnable [0xffffffff578fe000..0xffffffff578ff928]
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:76)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w1" prio=10 tid=0x0000000100aa7680 nid=0x3a in Object.wait() [0xffffffff57afe000..0xffffffff57aff8a8]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xffffffff7211db78> (a java.lang.Object)
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:69)
        - locked <0xffffffff7211db78> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w0 [container1-13]" prio=10 tid=0x0000000101196f40 nid=0x39 in Object.wait() [0xffffffff57cfe000..0xfffffff
f57cff828]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xffffffff7211db78> (a java.lang.Object)
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:69)
        - locked <0xffffffff7211db78> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 첫번째 Thread w0 동기화 블록 진입 , object 오브젝트에 대해 wait 메서드를 호출 하면서 Object.wait()상태가 되었고, w1 뒤따라 동기화 블록에 진입하면서, object 오브젝트가 notify되기를 기다리면서 Object.wait()상태가 되었고, w2 Thread else절을 지나, finally절에 진입하여 for문을 수행 중이기 때문에, ‘runnable’ 나타나고 있다.

 

[HP-UX]

l          Thread 실행 순서 : w0 à w1 à w2

l          Dump 내용

"http1-w2" prio=3 tid=60000000024ffc40 nid=60 lwp_id=1583373 runnable [9fffffff786ff000..9fffffff78700a40]
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:76)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w1" prio=10 tid=60000000024bc480 nid=59 lwp_id=1583372 in Object.wait() [9fffffff78900000..9fffffff78900ac0
]
        at java.lang.Object.wait(Native Method)
        - waiting on <9fffffffb86c5a20> (a java.lang.Object)
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:69)
        - locked <9fffffffb86c5a20> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w0 [container1-13]" prio=10 tid=60000000024b6180 nid=58 lwp_id=1583371 in Object.wait() [9fffffff78b00000..
9fffffff78b00d40]
        at java.lang.Object.wait(Native Method)
        - waiting on <9fffffffb86c5a20> (a java.lang.Object)
        at jeus_jspwork._600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:69)
        - locked <9fffffffb86c5a20> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 역시 SunOS플랫폼의 결과와 유사하게 나타난다.

 

[AIX / JDK 1.5]

l          Thread 실행 순서 : w2 à w1 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w0 [container1-15]" (TID:0x0000000114B88000, sys_thread_t:0x00000001147E06D0, state:CW, native ID:0x000000
00003230B3) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:75)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:1 06)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/engine/ServletWrapper.execute(ServletWrapper.java:220)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.execute(JspServletWrapper.java:139)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w1 [container1-14]" (TID:0x0000000114C76E00, sys_thread_t:0x0000000114B88F30, state:CW, native ID:0x000000
00003DD0E7) prio=5
4XESTACKTRACE          at java/lang/Object.wait(Native Method)
4XESTACKTRACE          at java/lang/Object.wait(Object.java:231)

4XESTACKTRACE          at jeus_jspwork/_600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:68)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/engine/ServletWrapper.execute(ServletWrapper.java:220)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.execute(JspServletWrapper.java:139)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w2 [container1-13]" (TID:0x0000000114C7B600, sys_thread_t:0x0000000114B89410, state:CW, native ID:0x000000
00003E00DB) prio=5
4XESTACKTRACE          at java/lang/Object.wait(Native Method)
4XESTACKTRACE          at java/lang/Object.wait(Object.java:231)

4XESTACKTRACE          at jeus_jspwork/_600_thread_5fcw_5fjsp._jspService(_600_thread_5fcw_5fjsp.java:68)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/servlets/JspServlet.execute(JspServlet.java:359)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 첫번째와 두번째, 세번째 Thread 모두 ‘state:CW’ 나타나는 것을 있다.

하지만, w2 w1 Stack 보면, Object.wait 상태로 w0 차이가 있는 것을 있다.


[AIX / JDK 1.4]

l          Thread 실행 순서 : w1 à w2 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w2 [container1-17]" (TID:0x3031E040, sys_thread_t:0x387295A8, state:CW, native ID:0x393C) prio=5

4XESTACKTRACE          at java.lang.Object.wait(Native Method)

4XESTACKTRACE          at jeus_jspwork._500_thread_5fcw_5fjsp._jspService(_500_thread_5fcw_5fjsp.java:52)

4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)

4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)

4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)

4XESTACKTRACE          at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:213)

4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:140)

4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)

3XHNATIVESTACK       Native Stack

NULL                 ------------

3XHSTACKLINE         at 0xD012316C in _event_wait

3XHSTACKLINE         at 0xD012E9DC in _cond_wait_local

3XHSTACKLINE         at 0xD012EEB0 in _cond_wait

3XHSTACKLINE         at 0xD012F874 in pthread_cond_timedwait

3XHSTACKLINE         at 0xD22A6A10 in condvarTimedWaitUpTo248Days

3XHSTACKLINE         at 0xD22A6BA0 in condvarTimedWait

3XHSTACKLINE         at 0xD22A5988 in sysMonitorWait

3XHSTACKLINE         at 0xD215E57C in lkMonitorWait

3XHSTACKLINE         at 0xD20E1518 in JVM_MonitorWait

3XHSTACKLINE         at 0xD2086958 in

3XHSTACKLINE         at 0xD2116074 in sysInvokeNative

3XHSTACKLINE         at 0xD210D938 in mmipInvokeJniMethod

3XHSTACKLINE         at 0xD20EB708 in mmipExecuteJava

3XHSTACKLINE         at 0xD20E3334 in xeRunJavaVarArgMethod

3XHSTACKLINE         at 0xD20E35C8 in xeRunDynamicMethod

3XHSTACKLINE         at 0xD20D06D4 in threadRT0

3XHSTACKLINE         at 0xD216380C in xmExecuteThread

3XHSTACKLINE         at 0xD2167CAC in threadStart

3XHSTACKLINE         at 0xD229EE50 in _start

3XHSTACKLINE         at 0xD011167C in _pthread_body

3XHSTACKLINE         at 0xD011167C in _pthread_body

3XMTHREADINFO      "http1-w1 [container1-16]" (TID:0x3031E150, sys_thread_t:0x38726F28, state:CW, native ID:0x383B) prio=5

4XESTACKTRACE          at java.lang.Object.wait(Native Method)

4XESTACKTRACE          at jeus_jspwork._500_thread_5fcw_5fjsp._jspService(_500_thread_5fcw_5fjsp.java:52)

4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)

4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)

4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)

4XESTACKTRACE          at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)

4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)

3XHNATIVESTACK       Native Stack

NULL                 ------------

3XHSTACKLINE         at 0xD012316C in _event_wait

3XHSTACKLINE         at 0xD012E9DC in _cond_wait_local

3XHSTACKLINE         at 0xD012EEB0 in _cond_wait

3XHSTACKLINE         at 0xD012F874 in pthread_cond_timedwait

3XHSTACKLINE         at 0xD22A6A10 in condvarTimedWaitUpTo248Days

3XHSTACKLINE         at 0xD22A6BA0 in condvarTimedWait

3XHSTACKLINE         at 0xD22A5988 in sysMonitorWait

3XHSTACKLINE         at 0xD215E57C in lkMonitorWait

3XHSTACKLINE         at 0xD20E1518 in JVM_MonitorWait

3XHSTACKLINE         at 0xD2086958 in

3XHSTACKLINE         at 0xD2116074 in sysInvokeNative

3XHSTACKLINE         at 0xD210D938 in mmipInvokeJniMethod

3XHSTACKLINE         at 0xD20EB708 in mmipExecuteJava

3XHSTACKLINE         at 0xD20E3334 in xeRunJavaVarArgMethod

3XHSTACKLINE         at 0xD20E35C8 in xeRunDynamicMethod

3XHSTACKLINE         at 0xD20D06D4 in threadRT0

3XHSTACKLINE         at 0xD216380C in xmExecuteThread

3XHSTACKLINE         at 0xD2167CAC in threadStart

3XHSTACKLINE         at 0xD229EE50 in _start

3XHSTACKLINE         at 0xD011167C in _pthread_body

3XHSTACKLINE         at 0xD011167C in _pthread_body

3XMTHREADINFO      "http1-w0 [container1-13]" (TID:0x3031BDD0, sys_thread_t:0x38726928, state:R, native ID:0x373A) prio=5

4XESTACKTRACE          at jeus_jspwork._500_thread_5fcw_5fjsp._jspService(_500_thread_5fcw_5fjsp.java:59)

4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)

4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)

4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)

4XESTACKTRACE          at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:213)

4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:140)

4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)

3XHNATIVESTACK       Native Stack

NULL                 ------------

3XHSTACKLINE         at 0xD20EB708 in mmipExecuteJava

3XHSTACKLINE         at 0xD20E3334 in xeRunJavaVarArgMethod

3XHSTACKLINE         at 0xD20E35C8 in xeRunDynamicMethod

3XHSTACKLINE         at 0xD20D06D4 in threadRT0

3XHSTACKLINE         at 0xD216380C in xmExecuteThread

3XHSTACKLINE         at 0xD2167CAC in threadStart

3XHSTACKLINE         at 0xD229EE50 in _start

3XHSTACKLINE         at 0xD011167C in _pthread_body

3XHSTACKLINE         at 0xD011167C in _pthread_body

결과 설명 : 동기화 블록 안에서 object 오브젝트를 기다리는 Thread ‘state:CW’ 나타나고, finally절을 수행중인 w0 Thread ‘state:R’ 표시되고 있다.

 


deadlock 상태

상태는, 쉽게말해 두개의 Thread 동기화 블록 내부에서, 상대방의 method 호출하는 상황에서, 서로 상대방 Thread (key) 획득하기 위해, 무한정 대기하는 상황을 말한다.

이경우, JVM 그대로 Hangup상태에 빠지게 된다.

 

JDK1.5에서는, 이러한 동기화문제를 해결하기 위해 java.util.concurrent 패키지를 제공한다.

(기존 JSR-166)
java.util.concurrent
패키지에는 동기화,Lock,Queue,ThreadPool 더불어 동기화패턴에 사용될 있는, Time base class들이 추가되어 있다.

주요 클래스들은 아래와 같다.

 

* java.util.concurrent 패키지의 주요 Class

l          Thread pool

-. 캐시 Thread pool, 고정크기 Thread pool, 스케쥴링 Thread pool등을 지원한다.

l          Executor, Future

-. Executor interface, Thread 실행시키는 새로운 방법이며, 기존의 tart() 메서드를 대신하기도 하며, Callable 실행시키는 방법이다.

l          Future interface 비동기 방식으로 Thread 수행시킬 있도록 한다.

l          Queue Class

-. 블록킹 구조의 BlockingQueue interface , non-blocking 구조의 ConcurrentLinkedQueue 등이 있다.

l          세마포어 Class

-. ‘세마포어 내부적으로 숫자를 유지하고 있다가, acquire 호출 -1 수행하고,

release 호출 +1 증가시키는 방식으로 작동한다.

-. 결국 값이 ‘0’ 되면, acquire 요청한 Thread 대기상태로 만들고,

이렇게 하여 multi-threading 환경에서 하나의 resource 접근하는 Thread 개수를

제한하는 방식으로 작동한다.

l          ReadWriteLock 클래스

-. 쉽게 말해, ‘쓰기보다 읽기작업이 많은 multi-threading 환경에서, ‘읽기작업에 대한 배타적(exclusive) 접근을 막겠다는 것이다. 동시 접근을 허용한다.

l          이외에도 CyclicBarrier Class, CountDownLatch Class, Exchanger Class등이 있다.


[thread-deadlock.jsp]

코드설명 : 첫번째 Thread else루틴을 수행하며, object2 객체의 Monitor 대한 Lock 잡고, object1객체에 대해 동기화를 시키고, 해제하고를 계속 반복한다. 이때, 두번째 Thread 실행되면, if절을 타게 되고, object1 대한 Monitor 있을 , 순간적으로 동기화 블록으로 진입하여, object2 대한 Monitor 기다리고 있다. 하지만, object2 대한 Monitor 이미 Thread1 가지고 있으며, Thread1 Thread2 object1 Monitor 기다리게 된다.

따라서, deadlock condition 빠지게 된다.

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>thread-cw.jsp</title>

</head>

<body>

<%!

        public static Object object1 = new Object();

        public static Object object2 = new Object();

        public static int count = 1;

%>

<%

        if(count%2 == 0){

                count++;

                synchronized(object1){

                        for(long i = 0; i < 10000000000L; i++){

                                synchronized(object2){}

                        }

                }

        }else{

                count++;

                synchronized(object2){

                        for(long i = 0; i < 10000000000L; i++){

                                synchronized(object1){}

                        }

                }

        }

%>

</body>

</html>

 

 

[SunOS]

"http1-w1" prio=10 tid=0x00000001003d1cc0 nid=0x3a waiting for monitor entry [0xffffffff57afe000..0xffffffff57aff6
28]   at jeus_jspwork._600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:70)
        - waiting to lock <0xffffffff71857638> (a java.lang.Object)
        - locked <0xffffffff71857628> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w0 [container1-13]" prio=10 tid=0x00000001003d1950 nid=0x39 waiting for monitor entry [0xffffffff57cfe000..
0xffffffff57cff6a8]
        at jeus_jspwork._600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:77)
        - waiting to lock <0xffffffff71857628> (a java.lang.Object)
        - locked <0xffffffff71857638> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : 각각의 Thread, for 안에서 서로의 객체에 대한 Monitor 기다리면서 동기화 블록 안으로 진입을 대기 하고 있음으로,  ‘waiting for monitor entry’ 표시된다.

Stack 정보에는, 해당 Thread ‘0xffffffff71857638’ ‘0xffffffff71857628’ Locked하고 있는 정보를 있다.


 

[HP-UX]

"http1-w2 [container1-15]" prio=10 tid=60000000024ffc40 nid=60 lwp_id=1583373 waiting for monitor entry [9fffffff7
8700000..9fffffff78700a40]
        at jeus_jspwork._600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:77)
        - waiting to lock <9fffffffb8cde050> (a java.lang.Object)
        - locked <9fffffffb8cde060> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

"http1-w1 [container1-16]" prio=10 tid=60000000024bc480 nid=59 lwp_id=1583372 waiting for monitor entry [9fffffff7
8900000..9fffffff78900ac0]
        at jeus_jspwork._600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:70)
        - waiting to lock <9fffffffb8cde060> (a java.lang.Object)
        - locked <9fffffffb8cde050> (a java.lang.Object)
        at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:106)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:818)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:220)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:139)
        at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:265)

결과 설명 : SunOS 거의 유사한 패턴을 보이고 있다.

 


 

[AIX / JDK 1.5]

l          Thread 실행 순서 : w1 à w2 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w0 [container1-13]" (TID:0x0000000114A07100, sys_thread_t:0x00000001147764F0, state:B, native ID:0x0000000
000372005) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:76)
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/servlets/JspServlet.execute(JspServlet.java:359)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w1 [container1-14]" (TID:0x0000000114A15C00, sys_thread_t:0x0000000114A11350, state:B, native ID:0x0000000
0003D00BD) prio=5
4XESTACKTRACE          at jeus_jspwork/_600_thread_5fdeadlock_5fjsp._jspService(_600_thread_5fdeadlock_5fjsp.java:69(Compiled Code))
4XESTACKTRACE          at jeus/servlet/jsp2/runtime/HttpJspBase.service(HttpJspBase.java:106)
4XESTACKTRACE          at javax/servlet/http/HttpServlet.service(HttpServlet.java:818)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus/servlet/engine/ServletWrapper.execute(ServletWrapper.java:220)
4XESTACKTRACE          at jeus/servlet/jsp/JspServletWrapper.execute(JspServletWrapper.java:139)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:265)
3XMTHREADINFO      "http1-w2" (TID:0x0000000114C6C300, sys_thread_t:0x0000000114A11830, state:P, native ID:0x000000000008B031) prio=
5
4XESTACKTRACE          at sun/misc/Unsafe.park(Native Method)
4XESTACKTRACE          at java/util/concurrent/locks/LockSupport.park(LockSupport.java:169)
4XESTACKTRACE          at java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.jav
a:1793)
4XESTACKTRACE          at java/util/concurrent/LinkedBlockingQueue.take(LinkedBlockingQueue.java:379)
4XESTACKTRACE          at jeus/servlet/util/StandardQueue.get(StandardQueue.java:53)
4XESTACKTRACE          at jeus/servlet/engine/ThreadPoolManager.getConnection(ThreadPoolManager.java:332)
4XESTACKTRACE          at jeus/servlet/engine/HttpRequestProcessor.run(HttpRequestProcessor.java:95)

결과 설명 : java.util.concurrent 관련한 클래스들이 작동하고 있는 모습이 보인다.

경우, Dump Header 부분에서 아래와 같은 메시지가 같이 출력된다.

1LKDEADLOCK    Deadlock detected !!!
NULL           ---------------------
NULL
2LKDEADLOCKTHR  Thread "http1-w0 [container1-13]" (0x0000000114A07100)
3LKDEADLOCKWTR    is waiting for:
4LKDEADLOCKMON      sys_mon_t:0x0000000112E0C9E0 infl_mon_t: 0x0000000112E0CA30:
4LKDEADLOCKOBJ     
java/lang/Object@0700000002309EF8/0700000002309F10:
3LKDEADLOCKOWN    which is owned by:
2LKDEADLOCKTHR  Thread "http1-w1 [container1-14]" (0x0000000114A15C00)
3LKDEADLOCKWTR    which is waiting for:
4LKDEADLOCKMON      sys_mon_t:0x000000011498DA00 infl_mon_t: 0x000000011498DA50:
4LKDEADLOCKOBJ     
java/lang/Object@0700000002309F10/0700000002309F28:
3LKDEADLOCKOWN    which is owned by:
2LKDEADLOCKTHR  Thread "http1-w0 [container1-13]" (0x0000000114A07100)

 

 [AIX / JDK 1.4]

l          Thread 실행 순서 : w1 à w2 à w0

l          Dump 내용

3XMTHREADINFO      "http1-w1" (TID:0x304F7768, sys_thread_t:0x38E21528, state:CW, native ID:0x383B) prio=5
4XESTACKTRACE          at jeus_jspwork._500_thread_5fdeadlock_5fjsp._jspService(_500_thread_5fdeadlock_5fjsp.java(Compiled Code))
4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)
4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:213)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:140)
4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)
3XHNATIVESTACK       Native Stack
NULL                 ------------
3XHSTACKLINE         at 0x38EE6804 in
3XHSTACKLINE         at 0xD012316C in _event_wait
3XHSTACKLINE         at 0xD012E9DC in _cond_wait_local
3XHSTACKLINE         at 0xD012EEB0 in _cond_wait
3XHSTACKLINE         at 0xD012F874 in pthread_cond_timedwait
3XHSTACKLINE         at 0xD22A6A10 in condvarTimedWaitUpTo248Days
3XHSTACKLINE         at 0xD22A6BA0 in condvarTimedWait
3XHSTACKLINE         at 0xD22A5988 in sysMonitorWait
3XHSTACKLINE         at 0xD21604F4 in lkMonitorEnter
3XHSTACKLINE         at 0xD2318F08 in _jit_monitorEnterQuicker
3XHSTACKLINE         at 0xD2509220 in JITSigSegvHandler
3XHSTACKLINE         at 0x35339254 in
3XHSTACKLINE         at 0x35339254 in
3XMTHREADINFO      "http1-w0" (TID:0x304C93B0, sys_thread_t:0x38E20F28, state:MW, native ID:0x373A) prio=5
4XESTACKTRACE          at jeus_jspwork._500_thread_5fdeadlock_5fjsp._jspService(_500_thread_5fdeadlock_5fjsp.java(Compiled Code))
4XESTACKTRACE          at jeus.servlet.jsp.HttpJspBase.service(HttpJspBase.java:53)
4XESTACKTRACE          at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
4XESTACKTRACE          at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:94)
4XESTACKTRACE          at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:359)
4XESTACKTRACE          at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:251)
3XHNATIVESTACK       Native Stack
NULL                 ------------
3XHSTACKLINE         at 0xD230F26C in release_m_block
3XHSTACKLINE         at 0xD011D4A4 in _mutex_lock
3XHSTACKLINE         at 0xD22A66E4 in cooperative_mutex_lock
3XHSTACKLINE         at 0xD22A6334 in sysMonitorEnter
3XHSTACKLINE         at 0xD21604F4 in lkMonitorEnter
3XHSTACKLINE         at 0xD2318F08 in _jit_monitorEnterQuicker
3XHSTACKLINE         at 0xD2509220 in JITSigSegvHandler
3XHSTACKLINE         at 0x35339254 in

경우, Dump Header 부분에서 아래와 같은 메시지가 같이 출력된다.

1LKDEADLOCK    Deadlock detected !!!

NULL           ---------------------

NULL

2LKDEADLOCKTHR  Thread "http1-w1" (0x38E21528)

3LKDEADLOCKWTR    is waiting for:

4LKDEADLOCKMON      sys_mon_t:0x37C2A968 infl_mon_t: 0x00000000:

4LKDEADLOCKOBJ      java.lang.Object@30358DD0/30358DD8:

3LKDEADLOCKOWN    which is owned by:

2LKDEADLOCKTHR  Thread "http1-w0" (0x38E20F28)

3LKDEADLOCKWTR    which is waiting for:

4LKDEADLOCKMON      sys_mon_t:0x37C2A4F8 infl_mon_t: 0x38CF3AD4:

4LKDEADLOCKOBJ      java.lang.Object@30358DE0/30358DE8:

3LKDEADLOCKOWN    which is owned by:

2LKDEADLOCKTHR  Thread "http1-w1" (0x38E21528)

 


맺음말

지금까지 Thread dump생성 , 플랫폼 주요 Thread State 어떤 식으로 보여지는지 간략하게 살펴 보았다. 하지만, 실제 운영환경에서 발생하는 Java ThreadDump 상에는 보다 복잡 다단한 상황이 많이 벌어지게 마련이다. 문서는, 그러한 복합상황의 해석의 기초가 되는, Thread State 대해 주로 다뤄본 것이 목적이다.

지금까지 소개한 주요 패턴 이외에도, Thread 정상적으로 작동하는 처럼 보이지만, 실제로는 Hang-up상태로 빠지는 경우 등의 변수가 많이 존재한다. 실제로 그러한 이유로, Service 느려지거나, 멈추는 현상들이 주로 발생하는 것이 현실이다. 따라서, WAS 근간으로 하는 System에의 Thread Dump 분석 스킬을 향상시키기 위해서는, 해당 문서에서 다뤄본 Thread State 기초로 하여, 다양한 실제 Dump 많이 접해보는 것이 가장 좋은 방법이다.

문서에서 다뤄지지 않은 보다 자세한 내용은, Vendor 기술홈페이지나 관련서적을 참조하도록 한다.

 

l          IBM : http://www-1.ibm.com/support/docview.wss?fdoc=aimwas&rs=180&uid=swg21181068

l          SUN : http://java.sun.com/developer/onlineTraining/Programming/JDCBook/stack.html


출처 : http://blog.daum.net/_blog/BlogView.do?blogid=0JvJB&articleno=7577652#ajax_history_home
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
java -Xdump:what

위와 같이 하면 설정된 기본 옵션 나온다.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

kill -3 <PID>

요렇게 뜨자.
반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,