2015. 6. 24. 11:29

1. java -XX:+PrintFlagsFinal -version

 

2. Understanding CMS GC Logs

   https://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs

 

3. Tomcat 정보

   톰캣설치디렉토리/bin]# ./version.sh  또는  ./catalina.sh version
   Using CATALINA_BASE:   /usr/local/tomcat/lucy_8080
   Using CATALINA_HOME:   /usr/local/tomcat/lucy_8080
   Using CATALINA_TMPDIR: /usr/local/tomcat/lucy_8080/temp
   Using CATALINA_LOGDIR: /home/www/backup/tomcatlog
   Using JRE_HOME:       /usr/local/jdk6
   Server version: Apache Tomcat/5.5.17
   Server built:   Apr 14 2006 02:08:29
   Server number:  5.5.17.0
   OS Name:        Linux
   OS Version:     2.6.9-78.ELsmp
   Architecture:   i386
   JVM Version:    1.6.0_13-b03
   JVM Vendor:     Sun Microsystems Inc.

   (이거 말고 다르게 보는 방법)
   cat RELEASE-NOTES 
   $Id: RELEASE-NOTES 351503 2005-12-01 22:12:48Z keith $
   Tomcat 5.5 is designed to run on J2SE 5.0 and later, and requires

   마이너 버젼까 확인하기 위해서는.. jar 를 풀어서.. properties를 보면 확인이 가능합니다.
   jar xf /server/lib/catalina.jar  org/apache/catalina/util/ServerInfo.properties

   grep -r 'number' org/apache/catalina/util/ServerInfo.properties
  ./org/apache/catalina/util/ServerInfo.properties:server.number=5.5.17.0

 

 1. 톰캣이 설치된 경로로 이동(lib까지)

    위 경로가 아니면 명령어로 확인 불가


2. 다음의 명령어로 버전확인

   java -cp catalina.jar org.apache.catalina.util.ServerInfo

 

'Java' 카테고리의 다른 글

“top threads” plugin for JConsole  (0) 2014.12.16
Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Posted by 아도니우스
2014. 12. 16. 15:32

When working with large (server side) java application, sometimes it would be nice if you could look inside, to see what thread is taking up so much cpu time, and why. Something similar to the Unix top command, but then showing all threads in one (java) application, instead of all processes in the system.

When I was looking for such a monitoring application, I came accross the 2.0 version of MC4J that provides a “Thread Info” panel that displays threads together with CPU usage; exactly what I needed. Unfortunately, there is only an alpha release of this MC4J version, that is not yet perfectly stable. Moreover, the thread info panel doesn’t handle applications with large amounts of threads very well. As the source code of this version of MC4J is not (yet) publically available, this option turned out to be a dead end.

To my surprise, other applications with such functionality are hard to find. There are probably enough profiling applications that can do the job, but I wanted something simple, something JMX-based, that can used also to monitor applications running in production.

There is however something called JTop, which is a plugin for JConsole. It’s actually a demo for the new (since Java 6) JConsole plugin API, that does show CPU usage per thread. It’s fairly basic and only shows total CPU usage, which is not very usefull. You would expect that (after a year), somebody would have extended the demo to something more useful, but as I couldn’t find anything like that, I thought I should give it a try myself.

The result is a JConsole plugin that displays the top threads, sorted by cpu usage in the last sampling period. It also displays cpu usage history, and an average over the last 10 sampling periods.


 

To avoid ending up with an unresponsive user interface when monitoring applications with large number of threads, I took a few precautions. First of all, the plugin has it’s own refresh rate. It’s independent from the JConsole poll interval, which is 4 seconds by default. For applications with large amounts of threads, this is way too short: only retrieving all thread information can already take 4 or 5 seconds! Although you can change the JConsole poll interval with a command line option, I thought it would be more convenient to be able to change it from the monitoring panel. It’s default set to 10 seconds, which I think is reasonable in most cases. If you notice that cpu usage measurement takes too much of the application under test, just increase the sample period and see the RMI Connection thread that processes these request, sink in the list.

Another precaution was not to list all threads in the table. Displaying thousands of rows in a table is quite useless in any case, and I was afraid it would seriously harm performance. Eventually, diplaying that many rows turned out to be not much of a problem; I guess I still suffer from an prejudice with
respect to Swing performance…

Using MX4J also showed me that in a continuously refreshing table, it’s hard to select a thread in order to see it’s stacktrace. Therefore, in this plugin, tracing a thread is “sticky”: when you click a row in the table, the stacktrace of that thread is shown immediately and is refreshed with each new sample, until you deselect it or select another thread.

Even though having threads sorted by cpu usage is the logical thing to do, it’s not always convenient when you’re studying the results, as rows keeping moving with each refresh. To lock the rows to there current position, click the “fix order” button. The topmost rows (actually all rows with a non-zero cpu usage), will stay where they are. Rows that had a cpu usage of zero, but have a non-zero value in the next sampling periods, will appear just below these rows, to avoid that you oversee any thread that suddenly takes a large amount of cpu time.

You can run the plugin by downloading the jar-file and passing it to JConsole with the plugin option:
jconsole -pluginpath topthreads.jar. When JConsole connects, it should have a seventh tab named “top threads”.

'Java' 카테고리의 다른 글

JVM 현재 설정된 설정값 확인  (0) 2015.06.24
Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Posted by 아도니우스
2014. 12. 9. 10:13

Hotspot JVM GC 방식 

 

 Young Gen

 Old Gen

 GC 방식

 장/단점

 Serial GC

 Generation Algorithm

 Mark-Compact Algorithm

 1) Old 살아있는 객체 식별(Mark)

 2) 힙 앞부분부터 확인해 살아 있는 것만 남김(Sweep)

 3) 각 개체들이 연속되게 쌓이도록 가장 앞 부분부터 적재(Compact)

- 운영서버에 권고하지 않음

 Parallel GC

 Generation Algorithm

 (Thread 여러개)

 Mark-Compact Algorithm

 Serial GC와 동일하나 Young Gen을 병렬처리 하여 처리량을 늘림으로써 빠르게 객체를 처리할 수 있음

 

 Parallel Old GC

 Generation Algorithm

 (Thread 여러개)

 Parallel Compaction Algorithm (Mark-Summary-Compaction)

Summary 단계는 앞서 GC를 수행한 영역에 대해서 별도로 살아있는 객체를 식별한다는 점(Mark-Sweep-Compaction 차이)

- 기존 Parallel GC에서 Old Gen 처리량도 늘리자는 취지

 CMS

 Parallel Copy Algorithm

 Concurrent Mark-and-Sweep Algorithm

1) Initial Mark

2) Concurrent Mark

3) Remark

4) Concurrent Sweep

- 응답시간 개선에 집중

- 시간 절약 효과

 G1 GC

 Evacution Pause

 Concurrent Marking

1) Concurrent Marker가 각 힙 region 내의 살아있는 object 양 계산(Garbage가 많은 region 선택)

2) Young GC

   살아있는 object는 Survivor region과 Old region으로 이동(Stop-the-copy)

3) Compaction

   Large Chunk 로 Free space 병합 Fragmentaion 방지

  Fast Allocation Free List를 사용하지 않음, Linear 방식, TLAB 방식

- Gen 물리적 구분 사라짐

- 힙을 region으로 나눠 쪼개짐

- Garbage Object로 가득찬 Region 부터 Collection 수행

- copy 작업은 pause Time의 가장 큰 요인

 

※ 참고사이트 : http://dragon1.tistory.com/33

'Java' 카테고리의 다른 글

JVM 현재 설정된 설정값 확인  (0) 2015.06.24
“top threads” plugin for JConsole  (0) 2014.12.16
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Posted by 아도니우스
2014. 11. 1. 00:03
1. DB연결: JDBC 방식
2. 빈 객체 사용하지 않음
3. jstl 사용하지 않음
4. DB: oracle
5. 쿼리문 
create table member2(
idx number not null primary key,
id varchar2(20),
pw varchar2(16),
name varchar2(20),
age varchar2(3),
gender varchar2(2));

create sequence seq;

6. 폴더 구조
src
com.utill
  -DBConn.java

WebContent
  -loginForm.jsp
  -loginProcess.jsp
  -registForm.jsp
  -regist.jsp
  -main.jsp

DBConn.java
데이터 베이스 연결

package com.utill;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConn {
public static Connection conn = null;//커넥션 객체 생성

//데이터베이스 연결 메서드
public static Connection getConnection(){
  String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl";
  String id="scott";
  String pw="tiger";
  String driver="oracle.jdbc.driver.OracleDriver";
  
  try {
  Class.forName(driver);
  conn=DriverManager.getConnection(url,id,pw);
} catch (Exception e) {
System.out.println("접속 실패: "+e.toString());
}
return conn;
}//연결 메서드 종료
//데이터베이스 연결 종료 메서드
public static void dbClose(){
if(conn==null){
return;
}
try {
if(conn!=null){
conn.close();
}
} catch (Exception e) {
System.out.println("데이터 비정상 종료"+e.toString());
}
conn=null;
}
}//ClassEND

loginForm.jsp
로그인 페이지

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<form action="loginProcess.jsp" method="post">
<center>
<table border="1">
<tr>
<td>아이디</td>
<td><input name="id" type="text"/></td>
</tr>
<tr>
<td>비밀번호</td>
<td><input name="pw" type="password"/></td>
</tr>
<tr>
<td><input type="submit" value="login"/></td>
<td><a href="registForm.jsp"><input name="regist" type="button" value="회원가입"/></a></td>
</tr>
</table>
</center>
</form>
</body>
</html>

loginProcess.jsp
로그인 과정을 담당

<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="com.utill.DBConn"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
    
<%
request.setCharacterEncoding("EUC-KR"); //한글깨짐

//로그인 페이지로 부터 입력값을 받아 온다.
String id = request.getParameter("id");
String pw = request.getParameter("pw");

Connection conn = DBConn.getConnection();//데이터베이스 연결
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";

try{
sql="select * from member2 where id=?";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, id);
rs=pstmt.executeQuery();

if(rs.next()){
if(pw.equals(rs.getString("pw")) && id.equals(rs.getString("id"))){
session.setAttribute("id",id);//세션에 아이디 값을 저장
out.println("<script>");
out.println("location.href='main.jsp'");
out.println("</script>");
}
}
out.println("<script>");
out.println("location.href='loginForm.jsp'");
out.println("</script>");

 DBConn.dbClose();//데이터 베이스 닫기
}catch(Exception e){
e.printStackTrace();
}

%>

registForm.jsp
회원가입 폼

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<form action="regist.jsp" method="post">
<center>
<table border="1">
<tr>
<td>아이디:</td>
<td><input name="id" type="text"/></td>
</tr>
<tr>
<td>비밀번호:</td>
<td><input name="pw" type="text"/></td>
</tr>
<tr>
<td>이름:</td>
<td><input name="name" type="text"/></td>
</tr>
<tr>
<td>나이:</td>
<td><input name="age" type="text"/></td>
</tr>
<tr>
<td>성별:</td>
<td>
<input name="gender" type="radio" value="남" checked/>남자
<input name="gender" type="radio" value="여"/>여자
</td>
</tr>
<tr>
<td><input name="regist" type="submit" value="등록"/></td>
<td><input type="reset" value="다시입력"/></td>
</tr>
</table>
</center>
</form>
</body>
</html>

regist.jsp
회원 가입 과정을 담당

<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="com.utill.DBConn"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<%
request.setCharacterEncoding("EUC-KR"); //한글깨짐
String id = request.getParameter("id");
String pw = request.getParameter("pw");
String name = request.getParameter("name");
String age = request.getParameter("age");
String gender = request.getParameter("gender");
Connection conn = DBConn.getConnection();//데이터베이스 연결
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";
try{
sql="insert into member2(idx,id,pw,name,age,gender) values(seq.nextval,?,?,?,?,?)";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, pw);
pstmt.setString(3, name);
pstmt.setString(4, age);
pstmt.setString(5, gender);
int result = pstmt.executeUpdate();
DBConn.dbClose();
if(result!=0){
response.sendRedirect("loginForm.jsp");
}else{
response.sendRedirect("registForm.jsp");
}
}catch(Exception e){
e.printStackTrace();
}
%>

main.jsp
로그인 후 보여줄 페이지

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

<%
//세션에 아이디 값이 있으면(로그인 성공) 해당값을(형 변환 후) 전달 해 준다.
String id = null;
if(session.getAttribute("id")!=null){//if문으로써 로그인 상태와 비로그인 상태를 구분 할 수 있다.
id=(String)session.getAttribute("id");
}else{
out.println("<script>");
out.println("location.href='loginForm.jsp'");
out.println("</script>");
}
%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h3>로그인이 된 메인 페이지</h3>
안녕하세요<%=id %>님, 여기는 일반 회원 메뉴 입니다.<br/>
<%
if(id.equals("admin")){
%>
<a href="http://blog.naver.com/seilius" target="_blank"><b>관리자 메뉴</b></a>
<%} %>
</body>


'Java' 카테고리의 다른 글

“top threads” plugin for JConsole  (0) 2014.12.16
Hotspot JVM GC 방식  (0) 2014.12.09
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Heap 영역과 Stack 영역  (0) 2014.09.04
Posted by 아도니우스
2014. 10. 1. 18:28

Path클래스는 자바7에 있는 새로운 기능이면 NIO2에서 가장 널리 사용하는 클래스라고 합니다.

저도 처음 접하는거라 간단하게 API에 있는 기능 사용법만 샘플로 만들어봤습니다.


클래스 이름 그대로 경로를 조작하는데 있어서 강력한 기능을 제공합니다.

기존에는 경로를 조작하는데 있어서 File클래스를 사용하였으나 Path클래스로 대체해서 사용하면 참 좋을 것 같습니다.


[샘플 소스]

 

import java.io.File;
import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths; 
 
public class TestPath {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
 
		Path path = Paths.get("D:/test/Hellow.txt");
		// 경로 루트
		System.out.printf("Root   : %s \n" , path.getRoot());
		// 경로의 부모
		System.out.printf("Parent : %s \n", path.getParent());
		// 경로의 요소
		for (int i = 0; i < path.getNameCount(); i++) {
			System.out.printf("getNameCount %d : %s \n"  ,i, path.getName(i));	
		}
		// 서브경로
		System.out.printf("subu path : %s \n", path.subpath(0, path.getNameCount()));
		System.out.println();
 
		try {
			// 경로를 실제 경로로 변환
			// path가 실제로 존재하지 않으면 에러가 발생
			Path real_path = path.toRealPath(LinkOption.NOFOLLOW_LINKS);
			System.out.println(real_path);
 
			// 경로를 파일로 변환
			File path_to_file = path.toFile();
 
			// 파일에서 path추출
			Path file_to_path = path_to_file.toPath();
 
			// 파일에서 파일 이름
			System.out.printf("Path to file name : %s \n" , path_to_file.getName());
			// 파일에서 추출한 path에서의 경로
			System.out.printf("File to path      : %s \n" , file_to_path.toString());
 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 
	}
}

'Java' 카테고리의 다른 글

Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
singleton 패턴  (0) 2014.10.01
Heap 영역과 Stack 영역  (0) 2014.09.04
Java Hashtable  (0) 2014.06.16
Posted by 아도니우스
2014. 10. 1. 17:16

유일무이한 객체

  • 싱글턴패턴은 인스턴스가 하나 뿐인 특별한 객체를 만들 수 있게 해주는 패턴
  • 어떤 용도로 쓰는 건가?
    • 스레드 풀이라던가, 캐시, 대화상자, 사용자설정, 디바이스드라이버 등등 객체가 전체프로그램에서 오직 하나만 생성되어야 하는 경우에 사용
  • 그럼 전역변수로 static 으로 선언해서 사용하면 되지 않느냐?
    전역 변수로 객체를 생성하면 어플리케이션이 실행 될 때 객체가 생성될 것이다.(P208 맨밑줄)
    그 객체가 자원을 많이 차지 한다면 사용도 되기전에, 괜히 자원만 차지한다. 사용하지 않는다면 아무 쓸 데 없는 객체가 되겠지.

고전적인 싱글턴 패턴 구현법

  • 조심하세요.. 이 코드에 문제가 있다는 것을 알게 될 것입니다.
public class Singleton {
  
  //private으로 Sinleton클래스의 유일한 인스턴스를 저장하기 위한 정적 변수를 선언
  private static Singleton uniqueInstance;

  //생성자를 private로 선언했기 때문에 Singleton에서만 클래스를 만들 수 있다.
  private Singleton() {}

  //클래스의 인스턴스를 만들어서 리턴해 준다.
  public static synchronized Singleton getInstance() {
    if(uniqueInstance == null) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }

}

초콜릿 공장

  • 만약 애플리케이션에서 ChocolateBoiler 인스턴스가 두 개 이상 만들어지게 되면 어떤 문제가 생길까?

Non-Singleton Singleton
public class ChocolateBoiler {
  private boolean empty;
  private boolean boiled;
  
  private ChocolateBoiler() {
    //이 코드는 보일러가 비어있을 때만 돌아갑니다
    empty = true;
    boiled = false;
  }
  
  public void fill() {
    if (isEmpty()) {
      //보일러가 비어있을 때만 재료를 집어 넣습니다. 
      //원료를 가득 채우고 나면 empty와 boiled 플래그를 false로 설정합니다.
      empty = false;
      boiled = false;
      // 보일러에 우유/초콜릿을 혼합한 재료를 집어넣음
    }
  }
  
  public void drain() {
    //보일러가 가득 차 있고(비어있지 않고), 다 끓여진 상태에서만 
     //보일러에 들어있는 재료를 다음 단계로 넘깁니다. 
    //보일러를 다 비우고 나면 empty 플래그를 다시 true로 설정합니다. 
    if (!isEmpty() && isBoiled()) {
      // 끓인 재료를 다음 단계로 넘김
      empty = true;
    }
  }

 //보일러가 가득 차 있고 아직 끓지 않은 상태에서만 
 //초콜릿과 우유가 혼합된 재료를 끓입니다. 
 //재료가 다 끓고 나면 boiled 플래그를 true로 설정합니다   
  public void boil() {
    if (!isEmpty() && !isBoiled()) {
      // 재료를 끓임
      boiled = true;
    }
  }

  public boolean isEmpty() {
    return empty;
  }
  
  public boolean isBoiled() {
    return boiled;
  }
}
public class ChocolateBoiler {
  private static ChocolateBoilerSingleton cb;
  private boolean empty;
  private boolean boiled;
  
  private ChocolateBoiler() {
    empty = true;
    boiled = false;
  }

  public static ChocolateBoilerSingleton getInstance(){
    if(cb == null)
      cb = new ChocolateBoilerSingleton();

    return cb;
  }  
  
  public void fill() {
    if (isEmpty()) {
      empty = false;
      boiled = false;
    }
  }
  
  public void drain() {
    if (!isEmpty() && isBoiled()) {
      empty = true;
    }
  }


  public void boil() {
    if (!isEmpty() && !isBoiled()) {
      boiled = true;
    }
  }

  public boolean isEmpty() {
    return empty;
  }
  
  public boolean isBoiled() {
    return boiled;
  }
}

싱글턴 패턴의 정의

  • 싱글턴 패턴은 해당 클래스의 인스턴스가 하나만 만들어 짐
  • 어디서든지 그 인스턴스에 접근할 수 있도록 함
  • 클래스에서 자신의 단 하나뿐인 인스턴스를 관리하도록 만들면 됨

'Java' 카테고리의 다른 글

Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
Heap 영역과 Stack 영역  (0) 2014.09.04
Java Hashtable  (0) 2014.06.16
Posted by 아도니우스
2014. 9. 4. 16:43

* 프로그램에 메모리에 올라가게 되면 프로세스가 되는데 여기서 Data Segment와 Code Segment 로 나누어 지는데,

Heap 과 Stack 은 Date Segment를 이용

* Heap 은 런타임시 크기가 결정되는 요소들이 저장되는 공간

  - C의 malloc()이나 C++ 의 new로 메모리 할당이 될 때에는 Heap 영역에 메모리가 잡힌다.

* Stack 은 컴파일시 크기가 결정되어 있는 요소들이 저장되는 공간

  - 함수가 받는 매개 변수나 함수 내에서 사용되는 지역 변수가 Stack 영역에 저장

메모리를 가상으로 표현한 모습

Data 영역

전역 변수와 static 변수 저장 

 Heap 영역

동적할당 되는 데이터 자장(데이터가 위 부터 순차적으로 저장)

 Stack 영역

지역변수와 매개변수 저장(데이터가 아래부터 순차적으로 저장)

 

1. 메모리가 어떻게 할당되는지..(스택과 힙의 관계)

- Objective 타입 변수

- primitive 타입 변수

2. 클래스가 로딩되는 시점은?

 

3. static 변수들은 어디에 값이 저장되는지.

 

4. 이상적인 GC 그래프

'Java' 카테고리의 다른 글

Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Java Hashtable  (0) 2014.06.16
Posted by 아도니우스
2014. 6. 16. 12:40

import java.util.*;

class MyHash {
  public static void main(String args[]) {

    Hashtable<String,String> capitalCity = new Hashtable<String,String>();

    capitalCity.put("미국", "워싱턴"); // 해쉬에 아이템을 넣는 작업
    capitalCity.put("오스트리아", "빈");
    capitalCity.put("프랑스", "Paris");


    // 해시 속의 아이템 1개를 화면에 출력하기
    System.out.println(capitalCity.get("프랑스")); // 출력 결과: Paris
  }
}


cf) http://mwultong.blogspot.com/

'Java' 카테고리의 다른 글

Hotspot JVM GC 방식  (0) 2014.12.09
[모델1] 간단한 로그인 시스템  (0) 2014.11.01
Path 클래스 사용하기  (0) 2014.10.01
singleton 패턴  (0) 2014.10.01
Heap 영역과 Stack 영역  (0) 2014.09.04
Posted by 아도니우스