[java] 문자열 합치기, StringBuffer, String + String, concat 성능 비교

program/java 2012. 10. 7. 16:41
반응형

Q. 문자열을 합치는 방법인 StringBuffer, String + String, concat 의 성능을 비교한다.



※ 소스


String + String

for( int j = 0; j < 10; j++ )

{

String str = "";

start = System.nanoTime();

for( int i = 0; i < 10000; i++ )

str += String.valueOf( i );

end = System.nanoTime();

System.out.println( ( end - start ) + "(ns)" );

}

StringBuffer

for( int j = 0; j < 10; j++ )

{

StringBuffer strBuf = new StringBuffer();

start = System.nanoTime();

for( int i = 0; i < 10000; i++ )

strBuf.append( String.valueOf( i ) );

end = System.nanoTime();

System.out.println( ( end - start ) + "(ns)" );

}

concat

for( int j = 0; j < 10; j++ )

{

String str = "";

start = System.nanoTime();

for( int i = 0; i < 10000; i++ )

str = str.concat( String.valueOf( i ) );

end = System.nanoTime();

System.out.println( ( end - start ) + "(ns)" );

}




※ 결론


String + String

StringBuffer

concat 

219381486(ns)

211511302(ns)

207293854(ns)

210680966(ns)

208196763(ns)

208814199(ns)

208915404(ns)

203914398(ns) -> BAD

205495126(ns)

206599593(ns)

3971662(ns)

1469033(ns)

1302910(ns)

1094546(ns)

1116375(ns)

2104329(ns)

832036(ns) -> BEST

843092(ns)

840541(ns)

865488(ns)

110126748(ns)

103956922(ns)

102395471(ns)

103247069(ns)

102242388(ns)

101415170(ns) -> BAD

105201432(ns)

103828218(ns)

104164435(ns)

103972796(ns)



음.. 결과적으로는 StringBuffer, concat, String + String 순으로 빨랐다.


예상외로 StringBuffer 가 빠르다.



+ 추가(2012.05.08)


아래와 같은 String + String 의 경우 


System.out.println("x:"+x+" y:"+y);


컴파일러는 위 부분을 StringBuilder() 라는 객체 변환하여 실행한다.


System.out.println((new StringBuilder()).append("x:").append(x).append(" y:").append(y).toString());





String 은 Char[] 을 가지고 표현된다.


String 은 특성상 주소를 참조하지 않고 값을 복사하여 가지고 있는다.

(String 의 주소를 참조하여 값을 바꾸지 못하게 하기 위함)


String + String 을 하게 되면,


첫번째, 두번째 String 은 복사가 될 또다른 new String 으로 생성하여 복사하게 된다.


그러므로 String + String 복사시마다 새로운 String 객체가 생성된다고 보면 된다.





그에 비해 StringBuffer 는 최초 생성된 StringBuffer 에 계속되어 append 가 되기 때문에,


객체 생성이 줄어 속도와 리소스 면에서 우위에 있다.




참조 : http://ralf79.tistory.com/89

참조 : http://kaioa.com/node/59

반응형

[java] Iterator 사용법과 성능 비교

program/java 2012. 10. 7. 16:34
반응형

Q. Iterator 사용법과 성능 비교




1. Iterator 의 사용 법은 아래와 같습니다.


class IteratorForTest
{
	public static void main( String[] args )
	{
		ArrayList list = new ArrayList();
		for( int i = 0; i < 20; i++ )
			list.add( i );

		for( Iterator itr = list.iterator(); itr.hasNext(); )
			System.out.print( list.get( itr.next() ) + " " );
	}
}


class IteratorWhileTest
{
	public static void main( String[] args )
	{
		ArrayList list = new ArrayList();
		for( int i = 0; i < 20; i++ )
			list.add( i );

		Iterator itr = list.iterator();
		while( itr.hasNext() )
			System.out.print( list.get( itr.next() ) + " " );
	}
}

Iterator 를 활용해서 list의 모든 값을 가져온다.




2. Iterator VS List 의 Size 이용하기


for( Iterator<Integer> itr = list.iterator(); itr.hasNext(); )

{

list.get( itr.next() );

}

 1 : 0.309012652(sec)

 2 : 0.309870762(sec)

 3 : 0.310434898(sec)

 4 : 0.311340917(sec)

 5 : 0.312230778(sec)

 6 : 0.312908024(sec)

 7 : 0.313480948(sec)

 8 : 0.314196465(sec)

 9 : 0.314853301(sec)

10 : 0.31523232(sec)

int size = list.size();

for( int i = 0; i < size; i++ )

{

list.get( i );

}

 1 : 0.041885812(sec) 乃 Best

 2 : 0.041918697(sec)

 3 : 0.042251792(sec)

 4 : 0.04225406(sec)

 5 : 0.042269085(sec)

 6 : 0.042285244(sec)

 7 : 0.042312175(sec)

 8 : 0.042338539(sec)

 9 : 0.042373124(sec)

10 : 0.042443145(sec)




3. 결론


Iterator 는 자동으로 Index 를 관리해주기 때문에,


사용에 편리함이 있을수 있으나,


Iterator 를 열어보면 객체를 만들어 사용하기 때문에 느리다.


그러므로, list 의 size 를 받아서 사용하는 것이 더 좋다.


반응형

[java] for 문의 각 Operator(Inner Size, Outer Size, Colon Operator) 별 속도 차이

program/java 2012. 10. 7. 16:22
반응형

비슷한 기존 글 : http://www.850530.com/51


Q. for 문을 이용하여 for 문 안의 Operator 를 변경하여
ArrayList와 Array(배열) 을 값을 가져오는 처리 속도를 비교한다.

※ 테스트 장비

1. CPU : AMD FX-4100 Quad-Core Processor

2. Ram : PC3-12800 2G * 2

3. OS : Windows 7 (32-bit)

4. java : Sun Java JRE 1.6.0.24


※ 유의사항

각 장비의 성능에 따라서 다른 결과치를 보일수 있음.

위 테스트 장비를 기준으로 처리했을때를 기준으로 평가함.



※ 테스트 프로그램


public class SeqNumber

{

private int seq;

/*getter, setter 생략*/

}


ArrayList<SeqNumber> info = new ArrayList<SeqNumber>();

int inRoopSize = 1000000;


for( int i = 0; i < inRoopSize; i++ )

{

SeqNumber seq = new SeqNumber();

seq.setSeq( i );

info.add( seq );

}


※ ArrayList get 테스트 Operator


 1. Inner Size

start = System.nanoTime();

for( int i = 0; i < info.size(); i++ )

{

info.get( i ).getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );


2. Outer Size

start = System.nanoTime();

int size = info.size();

for( int i = 0; i < size; i++ )

{

info.get( i ).getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );


3. New Type Operator : Colon Operator

start = System.nanoTime();

for( SeqNumber lst : info )

{

lst.getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );



1. Inner Size 

2. Outer Size 

3. Colon Operator 

0.005541824(sec)

0.005524248(sec)

0.005493065(sec)

0.005518578(sec)

0.005482009(sec) 乃

0.005486828(sec)

0.005467551(sec)

0.005507239(sec)

0.00549505(sec)

0.005506955(sec)

☞ Good (까비)

0.005351606(sec)

0.005340551(sec)

0.005376269(sec)

0.005351039(sec)

0.005370883(sec)

0.005331763(sec) 

0.005389876(sec)

0.005414256(sec)

0.005352173(sec)

0.005335731(sec)

☞ Best (오오)

0.028813856(sec)

0.028473959(sec) 

0.029103576(sec)

0.028899468(sec)

0.028646601(sec)

0.029743115(sec)

0.029102158(sec)

0.028849574(sec)

0.029152052(sec)

0.028638947(sec)

☞ Bad (쓰레기 -_-)





그러나 ! 저런 구린 성능을 내는데 ! 필요가 없는것이냐 ?!


ArrayList 를 돌렸을때는 위와 같이 성능을 내는데,


List가 아닌 배열(Array)로 선언해서 돌리게되면 말이 달라집니다.




※ 배열(Array) get 테스트 Operator


 1. Inner Size

start = System.nanoTime();

for( int i = 0; i < info.length; i++ )

{

info[i].getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );


2. Outer Size

start = System.nanoTime();

int size = info.length;

for( int i = 0; i < size; i++ )

{

info[i].getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );


3. New Type Operator : Colon Operator

start = System.nanoTime();

for( SeqNumber lst : info )

{

lst.getSeq();

}

end = System.nanoTime();

System.out.println( ( ( (double)( end - start ) / 1000000000 ) ) + "(sec)" );



1. Inner Size 

2. Outer Size 

3. Colon Operator 

0.003044048(sec)

0.003147237(sec)

0.003017117(sec)

0.002984233(sec) 乃

0.003989467(sec)

0.003142701(sec)

0.003753608(sec)

0.003117754(sec)

0.003025622(sec)

0.003216974(sec)

☞ Good (얘도 까비)

0.002951917(sec)

0.002892101(sec)

0.00294653(sec)

0.002955885(sec)

0.002942844(sec)

0.002953051(sec)

0.002914213(sec)

0.002881896(sec) 乃

0.002976863(sec)

0.002943412(sec)

☞ Good (까비)

0.002832003(sec)

0.002832287(sec)

0.002842491(sec)

0.002911095(sec)

0.002850712(sec)

0.00283342(sec)

0.002797701(sec) 乃

0.002863469(sec)

0.00283994(sec)

0.002911094(sec)

☞ Best (오오)






※ 결론


당연히 생각해보면 0.001 ~ 0.0001초 차이는 체감하기엔 극히 적은 차이이다. 

구글에서 검색해본결과도 위 구문 모두 크게 차이를 나타내지 않는다고 한다.


그렇다고해서, 체감하기 적은 차이라고 해서 무시하고 사용할수 있을까 ?


어쨌든 빠른게 낫다 ?


무조건 빠른것을 원한다면 어셈블러로 코딩하는게 맞다.

우리가 자바로 프로그램을 하는 이유가 있듯이 각 문법에 장단점이 있지만,

각 프로그램에서 요구하는 형태의 상황에 따라서 적절히 쓰는게 중요하다 !

(절대, 저건 좋고 저건 나쁘다는게 아님 !)


컴파일러가 변환을 해줄때에 가장 최적의 어셈블러로 변환은 해주겠지만,

퍼포먼스를 컴파일러에만 의존하는것만이 좋은것은 아니다.


역시나 유저가....... ㅠ_ㅠ

반응형

[java] 우편번호 DB에 가져오기, 우편번호 검색기 넣는 방법

program/java 2012. 10. 5. 11:32
반응형

Q. 우편번호 검색기를 추가해보자.


인터넷을 돌아다니다 보면 회원가입 페이지에서 우편번호 검색하는 부분이 있다.


그런식으로 검색을 하기 위해선 우편번호DB 가 필요하다.






1. 우편번호DB 제공 사이트 방문


홈페이지 : http://www.zipfinder.co.kr/

우편번호DB : http://www.zipfinder.co.kr/zipcode/index.html

"우편번호 원본파일" 메뉴를 클릭하면 우편번호DB 파일이 보여진다.




2. 우편번호DB 선택


각 메뉴중 자기가 필요한 파일을 선택하여 다운받는다.

필자는 Type 3(txt) 로 하였다.




3. DB 만들기


위에서 받은 파일 각 Type의 컬럼 대로 테이블을 생성한다.

예) Type 3


CREATE TABLE POST
(
    SEQ                  INTEGER NOT NULL ,
    ZIPCODE              CHAR(7) NULL ,
    SIDO                 VARCHAR2(30) NULL ,
    GUGUN                VARCHAR2(30) NULL ,
    DONG                 VARCHAR2(30) NULL ,
    RI                   VARCHAR2(50) NULL ,
    ST_BUNJI             VARCHAR2(10) NULL ,
    ED_BUNJI             VARCHAR2(10) NULL 
);

ALTER TABLE POST  ADD  PRIMARY KEY (SEQ);




4. DB파일을 INSERT 하기 좋게 변환


DB파일을 열어 처리하게 쉽게 변환한다.

1번 라인의 컬럼명을 지운다.

예)Type 3

(ZIPCODE SIDO GUGUN DONG RI ST BUNJI ED_BUNJI SEQ) 삭제


그리고 맨 마지막 빈공간 라인을 삭제한다.

맨 마지막 라인의 데이터가 존재해야한다.


마지막으로 탭으로 구분되어 있는 구분기호를 '|' 로 바꾼다.

메모장이나 텍스트에디터로 탭을 -> '|' 기호로 전체를 바꾼다.




5. 프로그래밍을 해서 DB에 INSERT 한다.


import java.io.*;
import java.sql.*;

public class PostalNumberMig
{
	public static void main( String[] args ) throws Exception
	{
		Class.forName( "oracle.jdbc.driver.OracleDriver" );

		PreparedStatement stmt = null;
		Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:ORCL", "id", "pw" );

		try
		{
			conn.setAutoCommit( true );
			stmt = conn.prepareStatement( "INSERT INTO POST( SEQ, ZIPCODE, SIDO, GUGUN, DONG, RI, ST_BUNJI, ED_BUNJI ) VALUES( ?, ?, ?, ?, ?, ?, ?, ? ) " );

			BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( "post1.txt" ), "euc-kr" ) );

			try
			{
				int totCnt = 0;
				int cnt = 0;
				String s;

				long start = System.nanoTime();
				while( ( s = reader.readLine() ) != null )
				{
					totCnt++;
					int charCnt = 0;
					int seq = totCnt;

					String zipcode = s.substring( 0, 7 );

					charCnt = zipcode.length() + 1;
					String sido = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					charCnt += sido.length() + 1;
					String gugun = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					charCnt += gugun.length() + 1;
					String dong = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					charCnt += dong.length() + 1;
					String ri = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					charCnt += ri.length() + 1;
					String st_bunji = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					charCnt += st_bunji.length() + 1;
					String ed_bunji = s.substring( charCnt, s.indexOf( '|', charCnt ) );

					stmt.setInt( 1, seq );
					stmt.setString( 2, zipcode.trim() );
					stmt.setString( 3, sido.trim() );
					stmt.setString( 4, gugun.trim() );
					stmt.setString( 5, dong.trim() );
					stmt.setString( 6, ri.trim() );
					stmt.setString( 7, st_bunji.trim() );
					stmt.setString( 8, ed_bunji.trim() );

					stmt.addBatch();
					cnt++;

					if( cnt == 50000 )
					{
						cnt = 0;
						stmt.executeBatch();
					}
				}

				if( cnt > 0 )
					stmt.executeBatch();

				long end = System.nanoTime();
				System.out.println( ( end - start ) + "(ns)" );
			}
			finally
			{
				reader.close();
			}

			conn.commit();
		}
		finally
		{
			if( stmt != null )
				try
				{
					stmt.close();
				}
				catch( Exception e )
				{
				}
			conn.close();
		}
	}
}



반응형

[java] for 문에서 객체의 size 선언법

program/java 2012. 10. 5. 11:27
반응형

Q. for 문에서 객체의 size 위치별 성능 차이를 알아보자.




ArrayList arr = new ArrayList();

for( int i = 0; i < 1000000; i++ )
	arr.add( i );

for( int i = 0; i < arr.size(); i++ )
	arr.get( i );


보다는


ArrayList arr = new ArrayList();

for( int i = 0; i < 1000000; i++ )
	arr.add( i );

int size = arr.size();
for( int i = 0; i < size; i++ )
	arr.get( i );


위에와 아래와의 차이는 for 구문에 객체.size() 를 넣느냐의 차이이다.


실제로 소스를 돌려본결과 0.01초 정도의 미묘한 차이를 보였다.


그렇게 따지면 아주 약간의 차이만 있다는 뜻이다.




결론


for 구문 속에 객체.size() 가 있으면 계속해서 객체의 size 를 읽어드리는 불필요한 작업을 하게된다.


그렇기 때문에 for 문 밖에 int 를 선언하여 size를 저장한다음


for문을 돌려보는걸 권한다.




※ 검증시 아주 미묘한(0.01초) 차이였다. 하지만 좋은 프로그래밍을 위한 습관을 들이는 것이 중요하다.

반응형

[java] 문자열(String) 나누기, Split VS SubString

program/java 2012. 10. 5. 11:21
반응형

Q. "|"로 구분된 문자열(String)을 "|" 단위로 일부 추출하여 List 에 저장한다.
"|" 로 문자열을 자를때 Split과 SubString 의 속도를 비교한다.

ex) 100100|017|1|서울체신청|Y|


소스코드

import java.io.*;
import java.util.ArrayList;

public class StrSplitVsSubString
{
	public static void main( String[] args ) throws Exception
	{
		BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( "post.txt" ), "euc-kr" ) );

		int cnt = 0;
		int totCnt = 0;
		String s;

		ArrayList list = new ArrayList();

		long start = System.nanoTime();
		while( ( s = reader.readLine() ) != null )
		{
			cnt++;
			if( false )
			{
				String[] arr = s.split( "|" );
				list.add( arr[3] );
			}
			else
			{
				String no = s.substring( 0, 6 );
				int index1 = s.indexOf( '|', 11 );
				int index2 = s.indexOf( '|', index1 + 1 );
				String address = s.substring( index1 + 1, index2 );
				list.add( address );
			}
		}

		if( cnt > 0 )
			System.out.println( "\n\nTotal : " + ( totCnt + cnt ) );

		long end = System.nanoTime();
		System.out.println( ( end - start ) + "(ns)" );
	}
}



결과


 Split

SubString 

1018486826(ns) => 1.01초

1019984754(ns) => 1.01초

1023826810(ns) => 1.02초

1021068796(ns) => 1.02초

1031451956(ns) => 1.03초

163028956(ns) => 0.16초

172060749(ns) => 0.17초

163285509(ns) => 0.16초

166215880(ns) => 0.16초

165033753(ns) => 0.16초



결론


1. Split

Split은 Pattern.compile 객체를 new 로 생성하여 문자열을 자른다.

결과 값을 String[] 배열을 받아오기 때문에, String 배열 또한 생성해야 함으로 더 느려진다.


2. SubString

SubString 은 Split 보다 1/10 초 정도 줄어든 현상을 볼 수 있다.

SubString은 String의 value[] 라는 배열을 참조하여, offset(순번)과 count(총개수)만을 가지고 있다.

그러므로 객체를 생성하지 않은 SubString 이 보다 빠르다.


※ 성능을 고려하여 되도록 SubString을 쓰자.

반응형

[java] DB에 다량건 데이터 INSERT 시 excuteBatch() 사용

program/java 2012. 10. 5. 11:15
반응형

Q. 약 15만 라인의 데이터를 txt 파일을 읽어와서
DB에 INSERT 몇개 단위로 배치를 돌릴경우 가장 효율적인가?


Query를 excute 할 때, excuteUpdate()와 excuteBatch()의 성능을 테스트한다.




※ 소스코드


long start = System.nanoTime();
while( ( s = reader.readLine() ) != null )
{
	totCnt++;
	String no = s.substring( 0, 6 );
	int index1 = s.indexOf( '|', 11 );
	int index2 = s.indexOf( '|', index1 + 1 );
	String address = s.substring( index1 + 1, index2 );

	stmt.setInt( 1, totCnt );
	stmt.setString( 2, no );
	stmt.setString( 3, address );

	// case 1
	stmt.executeUpdate();

	// case 2
	stmt.addBatch();
	cnt++;

	if( cnt == 100 )
	{
		cnt = 0;
		stmt.executeBatch();
	}
}




1. 매번 excuteUpdate() 실행

  - 4분 이상의 작업에 인내심이 바닥남.... 중지함.


2. addbatch(), excuteBatch() 를 이용 100건당 실행

  - 39459776065(ns) => 3.9초


3. addbatch(), excuteBatch() 를 이용 500건당 실행

  - 11512822395(ns) => 1.1초


4. addbatch(), excuteBatch() 를 이용 1000건당 실행

  - 6683119024(ns) => 0.66초


5. addbatch(), excuteBatch() 를 이용 10000건당 실행 (BEST 乃)

  - 1442062299(ns) => 0.144초

  - 1423391208(ns) => 0.142초

  - 1475451583(ns) => 0.147초


6. addbatch(), excuteBatch() 를 이용 20000건당 실행 (Rank 3)

  - 1690612350(ns) => 0.16초

  - 1597981482(ns) => 0.15초


7. addbatch(), excuteBatch() 를 이용 30000건당 실행 (Rank 4)

  - 1608968179(ns) => 0.16초

  - 1619791589(ns) => 0.16초


8. addbatch(), excuteBatch() 를 이용 50000건당 실행 (Rank 2)

  - 1488951363(ns) => 0.148초

  - 1466872514(ns) => 0.146초





※ 결론.


1. 다량건 처리는 excuteUpdate 보다 excuteBatch 를 이용해야함!


2. batch 처리시 많은량을 batch로 넣는다해서 (무조건) 빨리 되는건 아님.


3. batch 처리할때에도 적당한 양 만큼 batch 로 처리하는것이 올바름.


4. 테스트 횟수와 각 장비들의 상태가 같지 않았기 때문에, 정확한 결론은 아님(참고할순 있지 않나..?)

반응형

[java] ? 연산, Question Mark 연산

program/java 2012. 10. 5. 11:04
반응형

Q. ? Question Mark 연산에 대해서 알아보자.




프로그램을 하다보면 매우 간단한 if 문장을 만들어야 할때가 있다.


형식을 갖춘 if 문장을 만들자니 귀찮고,


매우 간단히 해결하고 싶은 경우에는,


?, Question Mark 연산을 추천한다.



쉽게 생각하여 if 의 간략화된 조건문이라고 보면 된다.



public class QuestionMarkOperation
{
	public static void main( String[] args )
	{
		int a = 10;
		int b = 20;

		System.out.println( a > b ? a : b );
	}

}


아래는 구문 형식이다.


a > b ? a : b

조건식 ? 참 : 거짓

반응형

[gwt] 한글 깨짐 현상, css 목록 안불러와질때

program/java 2012. 10. 5. 10:56
반응형

Q. 한글 깨짐 현상과 css 목록 안불러와질때


gwt의 Design 화면이랑

Source 화면과의 한글이 다르게 나올때

브라우저의 텍스트가 깨져서 나올때




1. 설정 변경


Window > Preferences > General > Content Types


우측에 Content types:

Text > Java Source File 클릭

하단에 Default encoding: UTF-8


Text > CSS 클릭

하단에 Default encoding: UTF-8


(위 방법으로 안될시 아래 방법을 더 시도해보기 바람.)

(정확한 해결책은 아님.)



2. 이미 생성한 모든 파일의 재저장


기존 저장된 파일은 인코딩이 다를수 있으므로,

기존 파일을 열어 띄어쓰기하고 저장,

방금 입력한 띄어쓰기 삭제하고 저장

반응형

[java] 자바 환경변수 설정, java 환경변수 설정

program/java 2012. 10. 5. 10:53
반응형

Q. 자바 환경을 구성하기 위한 환경변수를 설정해보자.




1. 시스템 들어가기

Windows Key  + Break > 고급시스템 설정

OR

제어판 > 시스템 > 고급시스템 설정


2. 하단 환경변수 설정


3. 시스템 변수 > 새로 만들기

이름 : JAVA_HOME

값 : C:\Program Files\Java\jdk1.6.0_24


※ 설치된 경로까지만 지정


4. 시스템 변수 > path

이름 : path

값 : C:\Program Files\Java\jdk1.6.0_24\bin;


※ 설치된 경로의 bin 폴더 까지 지정



5. 확인

Windows Key + R

OR

시작 > 보조프로그램 > 실행


cmd 실행


C:\Users\User\>java -version 엔터

java version "1.6.0_24"

Java(TM) SE Runtime Environment (build 1.6.0_24-b07)

Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)


※ 버전은 다를수 있으나 출력 된다면, 제대로 설정이 완료된것임.

반응형