Cafe24에서 JNDI 사용시에 JNDI에 대한 설정내용을 반드시 /tomcat/conf/server.xml에 입력해주어야 합니다. /META-INF 폴더안에 context.xml 를 따로 생성하는 방식은 지원되지 않습니다. (Cafe24에서 tomcat 설정 파일 중 외부에 따로 생성할 수 있는 파일은 web.xml 파일 뿐입니다. 따로 생성한 web.xml 파일은 WEB-INF 폴더안에 넣어주면 됩니다.) 

server.xml의 수정은 SSH로 서버에 접속 후 vi 명령어를 이용해서 하면 됩니다. server.xml에서 수정할 내용은 아래와 같습니다. (새로 Context 태그를 추가하는 것이 아니라 기존의 Context 설정을 변경하는 것입니다. Cafe24에서는 기본적으로 Context 태그안의 JNDI 지정하는 부분에 주석처리가 되어있습니다. 따라서 주석 처리된 부분을 해제한 후 JDBC이름, DB이름, DB접속아이디, DB접속패스워드 부분을 변경해주시면 됩니다.) 

<Context path="" docBase="www"> 
   
<!-- Mysql JNDI --> 

   <Resource name="jdbc/JDBC이름(Cafe24에서는 기본적으로 아이디로 지정. 임의로 변경 가능)
     auth="Container" 
     type="javax.sql.DataSource" 
     driverClassName="com.mysql.jdbc.Driver" 
     url="jdbc:mysql://localhost/DB이름(Cafe24에서는 아이디가 DB명)
     username="DB접속 아이디
     password="DB접속 패스워드
     maxActive="20" 
     maxIdle="10" 
     maxWait="3000"
     validationQuery="select 1" /> 

</Context> 

 
 

이와 함께 WebContent/WEB-INF/web.xml에도 JNDI 관련한 사항을 입력해주어야 합니다. 추가해야 할 내용은 아래와 같습니다.

<resource-ref> 
   <res-ref-name>jdbc/JDBC이름(Context안에 지정한 이름과 동일해야 함)</res-ref-name> 
   <res-type>javax.sql.DataSource</res-type> 
   <res-auth>Container</res-auth> 
</resource-ref> 




※ 주의할 점은 SqlMapConfig.xml 파일의 JDBC이름도 동일하게 통일시켜주어야 한다는 것입니다.

<!-- JNDI 연결 설정 -->

<transactionmanager type="JDBC">

   <datasource type="JNDI">

       <property name="DataSource"
                     value="java:comp/env/jdbc/JDBC이름(Context안에 지정한 이름과 동일해야 함)">

       </property>
   </datasource>

</transactionmanager>

 
Posted by 플라스틱라디오
TAG cafe24, JNDI
서버에 SSH2로 접속 한 후 명령창에 아래의 명령어를 입력하면 톰캣 서버를 재시작 할 수 있습니다.

tomcat/bin/startup.sh



반대로 서버를 정지시키고 싶으면 아래와 같은 명령어를 입력합니다. 

tomcat/bin/shutdown.sh



서버의 정상 작동 상태는 catalina.out 파일을 통해 확인할 수 있습니다. 아래의 명령어 입력 후 실행 시 파일의 마지막 부분에 Server startup in 874 ms 와 같은 문구가 있다면 톰캣이 정상적으로 구동된 것입니다.

tail tomcat/logs/catalina.out 

Posted by 플라스틱라디오
Cafe24 서버에 다른 환경에서 컴파일된 class 파일을 바로 업로드 하면 제대로 작동이 안될 가능성이 높습니다. 따라서 java 파일을 업로드한 후 Cafe24 서버에서 컴파일 해주어야 합니다. Cafe24의 FAQ에 설명되어 있는 서블릿 컴파일을 위한 기본적인 명령어는 다음과 같습니다. (띄어쓰기에 주의해서 입력해야 합니다.)

javac -d . -classpath /home/hosting_users/Cafe24아이디/tomcat/lib/servlet-api.jar 컴파일할파일이름.java




하지만 이는 서블릿을 컴파일하기 위한 명령어이고 iBatis나 Struts 등을 사용할 경우에는 이를 컴파일하기 위한 라이브러리를 classpath에 추가해야 합니다. 보통 ';' 나 ':'를 뒤에 붙여주어 추가하는데 Cafe24의 경우 ':'를 붙여 추가합니다. Cafe24의 서버에 업로드시 Library 파일은 /WEB-INF/lib 폴더안에 위치하므로 이 경로안에 있는 jar 파일 중 컴파일을 위해 필요한 jar 파일을 classpath에 추가해 주도록 합니다. 

javac -d . -classpath /home/hosting_users/Cafe24아이디/tomcat/lib/servlet-api.jar:/home/hosting_users
/Cafe24아이디/www/WEB-INF/lib/라이브러리파일이름.jar
컴파일할파일이름.java   




또한 만일 컴파일할 클래스가 본인이 직접 작성한 다른 패키지에 있는 클래스를 참조하는 경우 이 클래스파일들 또한 classpath에 추가해 주어야 합니다. 직접 작성한 class 파일들은 모두 /WEB-INF/classes 폴더안에 위치하므로 아래와 같이 이 경로를 그대로 추가해 주면 됩니다.

javac -d . -classpath /home/hosting_users/Cafe24아이디/tomcat/lib/servlet-api.jar:/home/hosting_users
/Cafe24아이디/www/WEB-INF/lib/라이브러리파일이름.jar:/home/hosting_users/Cafe24아이디/www/WEB
-INF/classes/
컴파일할파일이름.java




컴파일 명령어 중 javac -d 다음에 오는 것은 파일을 어느 위치에 컴파일 할 것이지 지정하는 부분인데 위의 경우처럼 '.'으로 표시하는 것은 현재 디렉토리에 컴파일 하겠다는 것을 의미합니다. 컴파일된 class 파일은 패키지명에 해당하는 디렉토리들을 자동으로 생성하므로 Cafe24 서버의 경우에는 /WEB-INF/classes/ 로 지정하면 편리합니다. 

javac -d  ./www/WEB-INF/classes/ -classpath /home/hosting_users/Cafe24아이디/tomcat/lib/servlet-api.jar:/home/hosting_users/Cafe24아이디/www/WEB-INF/lib/라이브러리파일이름.jar:/home/hosting_us
ers/Cafe24아이디/www/WEB-INF/classes/ 컴파일할파일이름.java




참고 : 건우농장 - 펌] Java classpath (UNIX와 Mac OS X) 관리하기 (한글)
Posted by 플라스틱라디오

아이군의 블로그에 안드로이드 앱 개발에 있어서 상당히 유용한 글이 있어서 퍼왔습니다. 



마메렐핀님(이동훈님) - 2009.06.05

성능을 위한 설계

안드로이드 애플리케이션의 속도는 빨라야만 합니다. 음, 효율적이어야 한다고 말하는 쪽이 더 정확할 듯싶네요. 다시 말해, 제한된 컴퓨팅 파워와 데이터 저장소, 작은 화면, 갑갑한 배터리 수명 같은 모바일 장치 환경에서 가능한 한 효율적으로 실행되어야 한다는 것입니다.

애플리케이션을 개발할 때에는 이것을 명심하세요. 듀얼코어 개발 컴퓨터에서 실행하는 에뮬레이터에서는 충분히 잘 작동할지도 모르지만, 모바일 기기에서 실행할 때엔 그리 잘 되지 않을 것입니다. — 최고 성능의 모바일 기기라도 일반적인 데스크탑 시스템의 성능을 따라잡을 수는 없습니다. 그런 이유로, 다양한 모바일 기기들에게 최상의 성능을 보장하기 위해 여러분은 효율적인 코드를 작성하도록 열심히 노력하셔야 합니다.

일반적으로, 빠르거나 효율적인 코드라는 것은 메모리 할당을 최소화 하고, 꽉 짜인 코드를 작성하고, 특정 프로그래밍 언어나 잠재적으로 성능상 문제가 될만한 프로그래밍 어법들을 피하는 것을 말합니다. 객체지향 용어로 말하자면, 이러한 일이 가장 빈번히 일어나는 곳은 메소드 레벨이며, 이와 비슷하게 실제 코드 라인들과 반복문 등에서 발생합니다 .

이 문서는 다음 주제들을 다룹니다:

소개

자원 제한적 시스템에는 두 가지 기본 규칙이 있습니다:

  • 필요 없는 일은 하지 말 것
  • 메모리 할당을 피할 수 있다면 그렇게 할 것

아래의 모든 팁들은 이 두 가지 기본 주의를 따르고 있습니다.

누군가는 이 페이지상의 많은 조언이 "섣부른 최적화"나 마찬가지라고 비판할지도 모릅니다. 미시 최적화는 때로는 효율적인 데이터 구조와 알고리즘을 개발하는 것을 더 어렵게 만든다는 것은 사실입니다. 하지만, 핸드셋과 같은 임베디드 기기에서는 때로는 별다른 선택지가 없습니다. 예를 들어, 여러분이 데스크탑에서 개발할 때 생각하는 VM의 성능에 대한 가정을 안드로이드에도 적용한다면, 여러분은 시스템 메모리를 소진해버리는 코드를 꽤나 작성해 버리고 말 것입니다. 이것은 여러분의 애플리케이션이 바닥을 기도록 할 수 있습니다 — 시스템에서 동작하는 다른 프로그램들에게 무엇을 하는지 지켜보세요!

이것이 바로 이 가이드라인이 중요한 이유입니다. 안드로이드의 성공은 여러분의 애플리케이션이 제공하는 사용자 경험(UX)에 달렸고, 사용자 경험이란 것은 여러분의 코드가 빠르고 팔팔하게 반응하는지, 아니면 느리고 무거운지에 달렸습니다. 모든 우리의 애플리케이션들은 같은 장치에서 동작할 것이기 때문에, 어떤 의미로, 우리 모두 함께 이 것들을 지키도록 최선을 다해야 합니다. 이 문서를 운전면허를 딸 때 배워야만 하는 도로교통법이라고 생각하세요: 모든 이가 따르면 문제없이 원활하겠지만, 따르지 않는다면 사고가 날 것처럼 말입니다.

자세한 내용을 다루기 전에, 간단한 주의사항입니다: 아래 설명된 대부분의 이슈들은 VM이 JIT 컴파일러이든 아니든 효과적입니다. 같은 기능을 수행하는 두 메소드가 있고 interpret 방식에서 foo()의 실행속도가 bar()보다 빠르다면, 컴파일 된 버전에서도 아마 foo()가 bar()과 비슷하거나 더 빠른 속도를 보여줄 것입니다. 컴파일러가 여러분을 "구해줄"것이라던가 충분히 빠르게 만들어줄 것이라고 의존하는 건 현명하지 못하다는 것이죠.

객체 생성을 피하라

객체의 생성은 결코 공짜가 아닙니다. 임시 객체들을 위해 쓰레드-당(per-thread) 할당 풀을 사용하는 세대형(generational) GC는 더 낮은 비용으로 할당 할 수 있지만, 메모리를 할당한다는 것은 메모리를 할당하지 않는 것 보다 언제나 더 높은 비용이 듭니다.

만약 사용자 인터페이스 루프에서 객체를 할당한다면, 주기적으로 가비지 컬렉션을 강요하게 될 것이고 사용자 경험에 있어서 조그마한 "딸꾹질(거북함)"을 만들게 될 겁니다.

그러므로, 필요로 하지 않는 객체 생성을 피해야 합니다. 도움이 될 몇 가지 예제들이 있습니다.

  • 입력 데이터 셋에서 문자열을 추출할 때, 복사 생성된 것 대신 원본 데이터의 부분문자열을 받으십시오. 새로운 String 객체가 만들어졌더라도 원본 데이터의 char[]을 공유할 것입니다.
  • 문자열을 반환하는 메소드가 있고 그 결과가 언제나 StringBuffer에 더해지게 되는 경우에 있다면, 짧은 수명의 임시 객체를 생성하는 대신 직접적으로 더해지는 방식으로 식별자와 구현방식을 바꾸세요.

좀 더 급진적인 아이디어는 다차원 배열을 병렬의 단일 일 차원 배열로 잘라내는 것입니다:

  • int 배열은 Integer 배열보다 더 좋습니다만, 이것으로 또한 int형의 두 병렬 배열이 (int,int) 객체의 배열보다 더 많이 효과적이라는 사실을 추론할 수 있습니다.
  • 만약 (Foo,Bar) 튜플로 저장하는 컨테이너를 구현할 필요가 있다면, 직접 만든 (Foo,Bar) 객체의 단일 배열보다 두 개의 병렬 Foo[] 와 Bar[] 배열이 일반적으로 더욱 더 좋다는 것을 기억하십시오. (물론, 다른 코드들이 접근해야 하는 API를 설계할 때에는 예외가 있습니다; 이 경우 작은 속도 향상을 노리는 것 보다 좋은 API설계가 항상 좋습니다. 그러나 여러분의 내부 코드를 작성할 때에는 가능한 한 효율적인 코드가 되도록 해야 하겠습니다.)

일반적으로, 가능하다면 짧은 수명의 임시 객체 생성을 피하십시오. 더 적은 객체들을 만든다는 것은 사용자 경험에 직접적인 영향을 주는 가비지 컬렉션 줄여줌을 뜻합니다.

네이티브 메소드를 사용하라

문자열을 처리할 때, String.indexOf(), String.lastIndexOf() 와 그 밖의 특별한 메소드를 사용하는 것을 주저하지 마십시오. 이 메소드들은 대체적으로, 자바 루프로 된 것 보다 대략 10-100배 빠른 C/C++ 코드로 구현이 되어있습니다.

이 조언의 반대적 측면은 네이티브 메소드를 호출하는 것이 interpret방식의 메소드 호출보다 더 비용이 높다는 것입니다. 피할 수 있다면, 사소한 계산에는 네이티브 메소드를 사용하지 마십시오.

인터페이스보다 가상 연결을 선호하라

여러분이 HashMap 객체를 하나 가지고 있다고 합시다. 여러분은 HashMap이나 제네릭 Map 으로 선언을 할 수 있습니다.

Map myMap1 = new HashMap();

HashMap myMap2 = new HashMap();

어떤것이 더 좋은가요?

전통적인 지혜에서는 Map을 사용해야 한다고 할 것입니다. Map 인터페이스를 구현한 어떤 것으로라도 구현체를 바꿀 수 있기 때문입니다. 전통적인 지혜는 전통적인 프로그래밍에는 맞습니다만, 임베디드 시스템에는 그다지 대단하지 않습니다. 인터페이스 참조를 통해 호출하는 것은 명확한 참조를 통한 가상 메소드 호출보다 2배 더 소요될 수 있습니다.

여러분이 하는 일에 적합하여 HashMap사용을 선택했다면 Map으로 호출하는 것은 거의 가치가 없습니다. 코드를 리팩터링 해 주는 IDE의 가능성을 고려해 보더라도, Map으로 호출하는 것은 큰 가치가 없습니다. 여러분이 코드의 방향을 확신하지 못한다 해도 말입니다. (다시금 이지만, 공용 API는 예외입니다: 작은 성능 고려보다 좋은 API가 언제나 으뜸입니다.)

가상 연결보다 정적 연결을 선호하라

만약 객체의 필드에 접근할 필요가 없다면, 여러분의 메소드를 정적(static)으로 만드세요. 가상 메소드 테이블을 필요로 하지 않기 때문에 그게 더 빠르게 불려집니다. 또한, 메소드 식별자를 보고 메소드 호출이 객체의 상태를 바꿀 수 없다고 말할 수 있으므로, 좋은 관습이 됩니다.

내부에서 Getter/Setter 사용을 피하라

C++와 같은 네이티브 언어에서 필드에 직접적으로 접근하는 것 (예. i = mCount) 보다 getter를 사용하는 것 (i = getCount())은 일반적인 관습입니다. 이 방법은 C++에서는 훌륭한 습관입니다. 왜냐하면 항상 접근을 inline화 할 수 있는 컴파일러를 사용하고 있고, 필드에 접근을 제한하거나 디버그 해야 한다면 언제나 코드를 추가할 수 있기 때문입니다.

안드로이드에서는 나쁜 생각입니다. 가상 메소드 호출은 인스턴스 필드 참조보다 더 비용이 높습니다. 일반적인 객체 지향 프로그래밍 관습에 따르거나, 공용 인터페이스에서 getter, setter을 가지는 것은 이치에 맞습니다. 그러나 클래스 내부에서는 언제나 직접적으로 필드 접근을 해야합니다.

필드 참조들을 캐시하라

객체의 필드에 접근하는 것은 지역 변수에 접근하는 것 보다 더 느립니다. 이렇게 작성하는 것 대신:

for (int i = 0; i < this.mCount; i++)

      dumpItem(this.mItems[i]);

이렇게 하십시오:

  int count = this.mCount;

  Item[] items = this.mItems;

 

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

      dumpItems(items[i]);

(멤버 변수라는 것을 명확히 하기 위해 명시적인 "this"를 사용하고 있습니다.)

유사한 가이드라인은, 결코 "for"문의 두 번째 조건에서 메소드를 호출하지 말라는 것입니다. 예를 들어, 다음 코드는 간단하게 int 값으로 캐쉬 할 수 있는 경우임에도 큰 낭비가 되는 getCount()메소드를 매번 반복 마다 실행하게 됩니다:

for (int i = 0; i < this.getCount(); i++)

    dumpItems(this.getItem(i));

인스턴스 필드를 한번 이상 접근해야 한다면, 지역 변수를 만드는 것 또한 좋은 생각입니다. 예를 들어:

    protected void drawHorizontalScrollBar(Canvas canvas, int width, int height) {

        if (isHorizontalScrollBarEnabled()) {

            int size = mScrollBar.getSize(false);

            if (size <= 0) {

                size = mScrollBarSize;

            }

            mScrollBar.setBounds(0, height - size, width, height);

            mScrollBar.setParams(

                    computeHorizontalScrollRange(),

                    computeHorizontalScrollOffset(),

                    computeHorizontalScrollExtent(), false);

            mScrollBar.draw(canvas);

        }

    }

mScrollBar 멤버 필드에 네 개의 분리된 참조가 있습니다. 지역 스택 변수로 mScrollBar를 캐싱 함으로써, 네 개의 멤버 필드 참조가 더욱 효율적인 네 개의 스택 변수 참조로 바뀌었습니다.

덧붙여 말하자면, 메소드 인자들은 지역 변수와 같은 성능 특성을 가집니다.

상수를 Final로 선언하라

클래스의 상단에 있는 다음 선언을 고려해 봅시다:

static int intVal = 42;

static String strVal = "Hello, world!";

컴파일러는 클래스가 처음 사용될 때 실행하게 되는 <clinit>라 불리는 '클래스 초기화 메소드'를 생성합니다. 이 메소드가 intVal에 42 값을 저장하고, strVal에는 클래스파일 문자 상수 테이블로부터 참조를 추출하여 저장합니다. 나중에 참조될 때 이 값들은 필드 참조로 접근됩니다.

이를 "final" 키워드로 향상시킬 수 있습니다:

static final int intVal = 42;

static final String strVal = "Hello, world!";

클래스는 더이상 <clinit> 메소드를 필요로 하지 않습니다. 왜냐하면 상수들은 VM에 의해 직접적으로 다루어 지는 '클래스파일 정적 필드 초기자'에 들어가기 때문입니다.intVal의 코드 접근은 직접적으로 정수 값 42를 사용할 것이고, strVal로의 접근은 필드 참조보다 상대적으로 저렴한 "문자열 상수" 명령을 사용하게 될 것입니다.

"final"으로 메소드나 클래스의 선언을 하는 것은 즉각적인 성능 이득을 주지는 못하지만, 특정한 최적화를 가능하게 합니다. 예를 들어, 컴파일러가 서브클래스에 의해 오버라이드될 수 없는 "getter"메소드를 알고 있다면, 메소드 호출을 inline화 할 수 있습니다.

여러분은 또한 지역 변수를 final로 선언할 수 있습니다. 하지만 이것은 결정적인 성능 이득은 없습니다. 지역 변수에는 오직 코드를 명확히 하기 위해서 "final"을 사용합니다 (또는 예를 들어 익명 내부 클래스를 사용해야 한다면 가능).

주의 깊게 향상된 반복문(Enhanced For Loop)을 사용하라

향상된 반복문(때로 "for-each"로 알려진 반복문)은 Iterable 인터페이스를 구현한 컬렉션들을 위해 사용될 수 있습니다. 이러한 객체들로, 반복자는 hasNext() 와 next()을 호출하는 인터페이스를 만들기 위해 할당됩니다. ArrayList의 경우 여러분이 직접 탐색하는 것이 좋을 수 있습니다만, 다른 컬렉션들에서는 향상된 반복문 구문이 명시적인 반복자의 사용과 동등한 성능을 보여줍니다.

그럼에도, 다음 코드로 향상된 반복문의 만족스러운 사용법을 볼 수 있습니다:

public class Foo {

    int mSplat;

    static Foo mArray[] = new Foo[27];



    public static void zero() {

        int sum = 0;

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

            sum += mArray[i].mSplat;

        }

    }



    public static void one() {

        int sum = 0;

        Foo[] localArray = mArray;

        int len = localArray.length;



        for (int i = 0; i < len; i++) {

            sum += localArray[i].mSplat;

        }

    }



    public static void two() {

        int sum = 0;

        for (Foo a: mArray) {

            sum += a.mSplat;

        }

    }

}

zero() 는 반복되는 매 주기마다 정적 필드를 두 번 부르고 배열의 길이를 한번 얻습니다.

one() 은 참조를 피하기 위해 지역 변수로 모든 것을 끌어냈습니다.

two() 는 자바 언어의 1.5버전에서 소개된 향상된 반복문 구문을 사용합니다. 컴파일러에 의해 생성된 코드는 배열 참조와 배열의 길이를 지역 변수로 복사해주어, 배열의 모든 원소를 탐색하는데 좋은 선택이 될 수 있습니다. 주 루프 내에 추가적인 지역 읽기/저장이 만들어지고(명백하게 "a"에 저장), one()보다 쪼금 느리고 4 바이트 길어지게 하긴 합니다.

좀 더 명확하게 모든 것을 종합하자면: 향상된 반복문 구문은 배열과 잘 동작하지만, 추가적인 객체 생성이 있게 되는 Iterable 객체와 함께 사용할 때엔 조심해야 합니다.

열거형(Enum)을 피하라

열거형은 매우 편리합니다, 그러나 불운하게도 크기와 속도 측면에서 고통스러울 수 있습니다. 예를들어, 다음의 코드는:

public class Foo {

   public enum Shrubbery { GROUND, CRAWLING, HANGING }

}

900 바이트의 클래스 파일 (Foo$Shrubbery.class) 로 변환됩니다. 처음 사용할 때, 클래스 초기자는 각각의 열거화된 값들을 표기화 하는 객체상의 <init>메소드를 호출합니다. 각 객체는 정적 필드를 가지게 되고 총 셋은 배열("$VALUES"라 불리는 정적 필드)에 저장됩니다. 단지 세 개의 정수를 위해 많은 코드와 데이터를 필요로 하게 됩니다.

다음 코드:

Shrubbery shrub = Shrubbery.GROUND;

는 정적 필드 참조를 야기합니다. "GROUND"가 정적 final int 였더라면, 컴파일러는 알려진 상수로서 다루고, inline화 했을 수도 있습니다.

물론, 반대적 측면에서 열거형으로 더 좋은 API를 만들 수 있고 어떤 경우엔 컴파일-타임 값 검사를 할 수 있습니다. 그래서 통상의 교환조건(trade-off)이 적용됩니다: 반드시 공용 API에만 열거형을 사용하고, 성능문제가 중요할 때에는 사용을 피하십시오.

어떤 환경에서는 ordinal() 메소드를 통해 정수 값 열거를 갖는 것이 도움이 될 수 있습니다. 예를 들어, 다음 코드를:

for (int n = 0; n < list.size(); n++) {

    if (list.items[n].e == MyEnum.VAL_X)

       // do stuff 1

    else if (list.items[n].e == MyEnum.VAL_Y)

       // do stuff 2

}

다음 코드로 대신합니다:

   int valX = MyEnum.VAL_X.ordinal();

   int valY = MyEnum.VAL_Y.ordinal();

   int count = list.size();

   MyItem items = list.items();



   for (int  n = 0; n < count; n++)

   {

        int  valItem = items[n].e.ordinal();



        if (valItem == valX)

          // do stuff 1

        else if (valItem == valY)

          // do stuff 2

   }

때로는, 보장할 수 없습니다만, 이것이 더 빠를 수 있습니다.

내부 클래스와 함께 패키지 범위를 사용하라

다음 클래스 정의를 고려해 봅시다:

public class Foo {

    private int mValue;



    public void run() {

        Inner in = new Inner();

        mValue = 27;

        in.stuff();

    }



    private void doStuff(int value) {

        System.out.println("Value is " + value);

    }



    private class Inner {

        void stuff() {

            Foo.this.doStuff(Foo.this.mValue);

        }

    }

}

여기서 주목해야 할 중요한 것은, 외부 클래스의 private 메소드와 private 인스턴스 필드에 직접 접근하고 있는 내부 클래스(Foo$Inner)를 정의했다는 것입니다. 이것은 적법하고, 코드는 기대했던 대로 "Value is 27"을 출력합니다.

문제는 Foo$Inner는 기술적으로는 (비밀로써) 완전히 분리된, Foo의 private 멤버로 직접적인 접근을 하는 것은 적법하지 못한 클래스라는 것 입니다. 이 차이를 연결짓기 위해, 컴파일러는 두 개의 합성 메소드를 만듭니다:

/*package*/ static int Foo.access$100(Foo foo) {

    return foo.mValue;

}

/*package*/ static void Foo.access$200(Foo foo, int value) {

    foo.doStuff(value);

}

내부 클래스 코드는 외부 클래스에 있는 "mValue" 필드에 접근하거나 "doStuff" 메소드를 부르기 위해 이 정적 메소드를 부릅니다. 이것은 이 코드가 결국은 직접적인 방법 대신 접근자 메소드를 통해 멤버 필드에 접근하고 있다는 것을 뜻합니다. 이전에 우리는 어째서 접근자가 직접적인 필드 접근보다 느린지에 대해 이야기 했었는데, 이 문제로서 "보이지 않는" 성능 타격 측면에서 특정 언어의 어법이 야기하게 되는 문제에 대한 예제가 될 수 있겠습니다.

이 문제는 내부 클래스가 접근하는 필드와 메소드 선언에 private 범위가 아닌 package 범위를 가지도록 함으로써 피할 수 있습니다. 이로써 더욱 빠르게 동작하게 되고 자동 생성되는 메소드에 의한 오버헤드를 제거할 수 있습니다. (불운하게도 이 또한 직접적으로 같은 패키지 내의 다른 클래스들이 필드들에 접근할 수 있다는 것을 뜻하게 되며, 모든 필드들은 private로 해야 한다는 표준적인 OO 관습에 거스르게 됩니다. 다시 한번 더 말하자면, 공용 API를 설계하게 된다면 이 최적화를 사용하는 것을 조심스럽게 고민해야만 할 것입니다.)

Float를 피하라

펜티엄 CPU가 출시되기 전, 게임 제작자들에겐 정수 계산에 최선을 다하는 것이 일반적이었습니다. 펜티엄과 함께 부동소수점 계산 보조 프로세서는 일체형이 되었고, 정수와 부동소수점 연산을 넣음에 따라 순수하게 정수 계산만을 사용하는 것 보다 게임은 더 빠르게 되었습니다. 자유롭게 부동소수점을 사용하는 것은 데스크탑 시스템에서는 일반적입니다.

불운하게도, 임베디드 프로세서에게는 빈번하게 하드웨어적으로 부동소수점 계산이 제공되지 않고 있어, "float" 와 "double"의 모든 계산이 소프트웨어적으로 처리됩니다. 어떤 기초적인 부동소수점 계산은 완료까지 대략 일 밀리 초 정도 걸릴 수 있습니다.

또한, 정수에서도 어떤 칩들은 하드웨어 곱셈을 가지고 있지만 하드웨어 나눗셈이 없기도 합니다. 이러한 경우, 정수 나눗셈과 나머지 연산은 소프트웨어적으로 처리됩니다 — 만약 해시 테이블을 설계하거나 많은 계산이 필요하다면 생각해 보아야 할 것입니다.

성능 예시 숫자 몇 개

우리의 몇 가지 아이디어를 설명하기 위해, 약간의 기초적인 행동들에 대해 대략적인 실행시간을 나열한 테이블을 만들었습니다. 이 값들은 절대적인 숫자가 아니라는 것을 주목해 주십시오: CPU시간과 실제 구동 시간의 조합이고, 시스템의 성능 향상에 따라 변화할 수 있습니다. 그러나 이 값들 사이에 관계를 적용해 보는 것은 주목할 만한 가치가 있습니다 — 예를 들어, 멤버 변수를 더하는 것은 지역 변수를 더하는 것보다 대략 네 배가 걸립니다.

행동 시간
지역 변수 더하기 1
멤버 변수 더하기 4
String.length() 호출 5
빈 정적 네이티브 메소드 호출 5
빈 정적 메소드 호출 12
빈 가상 메소드 호출 12.5
빈 인터페이스 메소드 호출 15
HashMap의 Iterator:next() 호출 165
HashMap의 put() 호출 600
XML로부터 1 View 객체화(Inflate) 22,000
1 TextView를 담은 1 LinearLayout 객체화(Inflate) 25,000
6개의 View 객체를 담은 1 LinearLayout 객체화(Inflate) 100,000
6개의 TextView 객체를 담은 1 LinearLayout 객체화(Inflate) 135,000
빈 activity 시작 3,000,000

맺음 말

임베디드 시스템을 위해 좋고 효율적인 코드를 작성하는 최선의 방법은 여러분이 작성하는 코드가 실제로 무엇을 하는지 이해하는 것 입니다. 여러분이 정말로 반복자를 할당하기를 원한다면, List에 향상된 반복문을 반드시 사용하십시오; 부주의한 부작용이 아닌 신중한 선택을 통해서 말입니다.

유비무환입니다! 무엇을 하는지 알고 하세요! 좋아하는 좌우명을 여기에 넣으세요, 그러나 언제나 여러분의 코드가 무엇을 하는지 주의 깊게 생각하고, 속도를 높이는 방법을 찾도록 경계하십시오.

Posted by 플라스틱라디오

안드로이드 코딩을 하면서 빈번하게 사용되는 것이 Activity의 this 입니다. 이는 Context를 상속한 Activity의 Context 객체를 얻기 위한 변수인데요.. Context 변수를 필요로하는 메서드를 사용할 때 주로 액티비티명.this의 형태로 많이 사용합니다.
하지만 이렇게 Activity의 this를 직접 받아올 경우 메모리릭이 발생할 확률이 높다고 합니다. 따라서 Activity의 this를 통해 Context 객체를 가져오는 것보다 가급적  Context.getApplicationContext()나 Activity.getApplication() 메소드를 통해 Context 객체를 얻어내는 것이 좋다고 하는 군요.

보다 자세한 내용은 아래의 링크를 참조하세요.

휴휴휴 - [번역] 안드로이드 메모리 릭 회피하기 
Posted by 플라스틱라디오

자바스크립트에서 키보드 이벤트를 받았을 때 키 값을 구별할 수 있는 Keycode (ACSII 코드) 목록입니다.



알파벳(대소문자 동일함)
Mozilla
IE
Opera
pseudo ASCII codes
a
65
b
66
c
67
d
68
e
69
f
70
g
71
h
72
i
73
j
74
k
75
l
76
m
77
n
78
o
79
p
80
q
81
r
82
s
83
t
84
u
85
v
86
w
87
x
88
y
88
z
90



기능키
Mozilla
IE
Opera
pseudo ASCII codes
Backspace
8
Tab
9
Enter
13
Shift
16
Control
17
Alt
18
Pause / Break
19
Caps Lock
20
ESC
27
Space
32
Page Up
33
Page Down
34
End
35
Home
36
왼쪽 방향키
37
윗 방향키
38
오른쪽 방향키
39
아래 방향키
40
Insert
45
Delete
46
왼쪽 Windows키
91
219
0
오른쪽 Windows키
92
220
0
메뉴키
93
0
Num Lock
144
Scroll Lock
145



숫자
Mozilla
IE
Opera
pseudo ASCII codes
0
48
1
49
2
50
3
51
4
52
5
53
6
54
7
55
8
56
9
57



키패드
Mozilla
IE
Opera
pseudo ASCII codes
0 / Ins
96 / 45
48 / 45
1 / End
97 / 35
49 / 35
2 / 아래 방향키
98 / 40
50 / 40
3 / Pg Dn
99 / 34
51 / 34
4 / 왼쪽 방향키
100 / 37
52 / 37
5
101 / 12
53 / 12
6 / 오른쪽 방향키
102 / 39
54 / 39
7 / Home
103 / 36
55 / 36
8 / 윗 방향키
104 / 38
56 / 38
9 / Pg Up
105 / 33
57 / 33
*
106
42
+
107
43
-
109
45
/
111
47
. / Del
110 / 46
78 / 46



F키
Mozilla
IE
Opera
pseudo ASCII codes
F1
112
F2
113
F3
114
F4
115
F5
116
F6
117
F7
118
F8
119
F9
120
F10
121
F11
122
F12
123



기호
Mozilla
IE
Opera
pseudo ASCII codes
; / :
59
186
59
59 / 58
= / +
107
187
61
61 / 43
, / <
188
44
44 / 60
- / _
109
189
45
45 / 95
. / >
190
46
46 / 62
/ / ?
191
47
47 / 63
` / ~
192
96
96 / 126
[ / {
219
91
91 / 123
\ / |
220
92
92 / 124
] / }
221
93
93 / 125
' / "
222
39
39 / 34




아래 링크로 가시면 키이벤트에 대해 테스트 해볼 수 있습니다.
Javascipt Key Event Test Script





출처 : OUTSIDER'S DEV STORY - Javascript 키보드 Keycode(ACSII Code) 목록
Posted by 플라스틱라디오
PuTTY의 실행창에서 한글이 깨져서 보이는 경우 글꼴을 변경하거나 인코딩방식을 변경해 주어야 합니다.

1. 글꼴 변경
PuTTY 설정창의 Window - Appearance에서 글꼴을 한글지원 글꼴로 변경

2. 인코딩 변경
PuTTY 설정창의 Window - Translation의 Remote character set:을 utf-8 등으로 변경

 

'웹프로그래밍 > PuTTY' 카테고리의 다른 글

PuTTY 에서 한글이 제대로 표시 안될 경우  (0) 2012.01.11
Posted by 플라스틱라디오
TAG putty, 한글
다음과 같이 자바스크립트에서 ArrayList 메소드를 정의하면 Java의 ArrayList와 동일하게 사용이 가능합니다.
  
//ArrayList 구현
function ArrayList(){
	this.array = new Array();
	this.add = function(obj){
		this.array[this.array.length] = obj;
	};
	this.iterator = function (){
		return new Iterator(this);
	};
	this.length = function (){
		return this.array.length;
	};
	this.get = function (index){
		return this.array[index];
	};
	this.addAll = function (obj){
		if (obj instanceof Array){
			for (var i=0;i<obj.length;i++){
				this.add(obj[i]);
			}
		} else if (obj instanceof ArrayList){
			for (var i=0;i<obj.length();i++){
				this.add(obj.get(i));
			}
		}
	};
}

function Iterator (arrayList){
	this.arrayList;
	this.index = 0;
	this.hasNext = function (){
		return this.index < this.arrayList.length();
	};
	this.next = function() {
		return this.arrayList.get(index++);
	};
}





출처 : Koders.com
Posted by 플라스틱라디오

정규 표현식이란?  

정규 표현식은 문자열에서 특정한 캐릭터 조합을 찾아내기 위한 패턴입니다. 이를 이용하면 좀 더 세밀한 방법으로 문자들을 검색할 수 있습니다.




자바스크립트에서 정규 표현식 생성  

자바스크립트에서 정규표현식 생성 방법으로는 2가지가 있습니다.

1. object initializers를 사용한 방법 

  정규표현 = /패턴/i or /패턴/g or /패턴/gi                                                  
  ex) var reg = /abc/i; 
  ※ 여기서 주의할 것은 표현식 바깥을 ""로 감싸지 않는다는 점입니다.

2. RegExp 객체의 constructor function을 사용한 방법 

  new RegExp("패턴", "i") or new RegExp("패턴", "g") or new RegExp("패턴", "gi")
  ex) var reg = new RegExp("abc", "i");




정규 표현식의 플래그 구성 요소  

정규 표현식에서 사용할 수 있는 플래그 구성 요소는 다음과 같습니다. 이들은 생략이 가능합니다.
 

g   완전일치 (발생할 모든 패턴에 대한 전역 검색)
i    대소문자 무시
gi  대소문자 무시하고 완전 일치 





 
출처 :  혼돈으로 이루는 질서 - 자바스크립트 정규표현식(JavaScript Regular Expression)
Posted by 플라스틱라디오

이클립스에서 전에는 잘 작동하던 struts2 웹애플리케이션이 갑자기 struts2 오류를 발생시키며 작동이 안되는 경우가 있습니다. 정확한 원인을 찾아서 정확한 대처법을 알아서 오류를 해결해야할테지만 일단은 대충 아래와 같은 방법을 사용하면 오류가 없어지더군요..



1. 먼저 struts2와 관련된 jar 파일들을 삭제한 후 다시 import 해 준 후 서버를 재실행하고 웹애플리케이션을 다시 실행합니다.

2. 그래도 여전히 오류가 발생할 경우 struts2 태그 사용을 위한 taglib 지시자의 uri 속성에 정의된 '/struts-tags'를 삭제한 후 다시 작성해서 저장한 다음 웹애플리케이션을 재실행합니다.

3. 여전히 오류가 없어지지 않았을 경우 web.xml의 struts2 사용을 위한 filter, filter-mapping 태그 내용을 삭제한 다음 다시 작성한 후 서버를 재실행하고 웹 애플리케이션을 다시 실행합니다.


 
Posted by 플라스틱라디오
TAG struts2


맨 위로