Java에서는 Static 변수의 Non static 초기화를 위해 Static Initializer를 지원한다.

이는 static final 변수를 주로 예외를 throw하는 함수의 return 값으로 초기화하는데 사용된다.


다음과 같이 사용하면 된다.


(ex)



public class Example {

private static final Lib val;

static{
Lib tmp = null;
try{
tmp = new Lib();
}catch(UnknownHostException e){
//생성자가 이 예외를 반환하므로 일반적인 방법으로는 선언과 동시에 초기화가 불가능하다.
}
}

}



 이는 Lazy Initialization 의 예시로, 이러한 테크닉을 이용하면 Lazy Instantiation 과 유사하게 디자인 패턴 내의 코드를 작업하는 데 있어서 유연성을 가져올 수 있다.


 위의 예제에서 val 이라는 멤버변수는 final 인데다가 static 변수이면서 유효한 Lib 형의 객체이다. 안전하면서도 효율적이다.

위의 코드는 심지어 Thread-safe 하기 때문에 멀티 스레드 환경에서도 문제 없다.

 또한 위의 주석에 설명이 달려있듯, 생성자 자체가 예외를 발생시키는 경우 위와 같이 바깥에서 Try Catch 로 감싸줌으로써 안전한 초기화가 가능하다.


 다만, 이런 형태에서 위의 변수 val, 즉, Static Initialized Variable 은 클래스로더에 종속되기 때문에, 매번 객체 생성 시, 서로 다른 클래스 로더에서 Static 코드 블록을 호출하게 된다. 


 만약 하고자하는 바가 싱글턴이거나, 외부 코드에 종속적이라면 추천되지 않는 패턴이다. (물론 그렇게 쓰이는 경우는 흔치 않다.)





 리눅스에서 Java를 백그라운드 프로세스로 실행하려 할 때 다음과 같이 뒤에 &를 붙여주면 된다. 

(사실 리눅스에서는 자바 뿐 아니라 프로세스 실행 시 &만 붙여주면 백그라운드로 실행된다.)


 $ java -jar {run.java} &


- 단, 위와 같이 백그라운드 프로세스는 터미널이 필요하기 때문에(터미널에 종속되는 것이다.) 터미널 종료시, 로그아웃 시 프로세스도 같이 종료된다.


 이를 지원하기 위한 명령어로 nohup 명령어가 있다.

 이를 이용하면 리눅스에서 SIGHUP을 받지 않는 프로세스를 만들 수 있다.

 터미널이 종료될 때 프로세스가 죽는 이유는 해당 프로세스가 쉘의 자식 프로세스로 지정되어 있기 때문이다.

 부모 프로세스가 죽을 때 던지는 SIGHUP 을 자식 프로세스가 받게 되어 죽게 되고, 이를 무시할 수 있는 nohup을 이용하여 죽지 않게 만들 수 있다.


$ nohup java 클래스명&


 이는 사용이 편리하나 중지, 재시작 등 서비스가 일반적으로 갖고 있는 제어 루틴을 갖지 못하기 때문에 외부 명령어로 Kill 등을 해야 한다. 물론 Kill을 할 때 프로세스의 동작 제어는 많은 예외처리를 요구하게 된다.


 Java의 JVM은 UNIX 계열의 시그널 처리를 할 수 없기 때문에 따로 처리를 해줘야 하는데 이러한 번거로움을 Apache Commons Daemon을 이용하면 쉽게 해결할 수 있다.

 Jsvc는 중지 및 제어 신호에 대해 지정된 메서드를 실행할 수 있게 해주는 인터페이스를 갖고 있다. 


 Jsvc를 이용하려면 Daemon 인터페이스를 구현해야 한다. 또 쓰레드로 실행되지 않을 시 종료처리가 원만하게 되지 않기 때문에 143 오류가 발생하므로 Runnable 형태로 구현해야 한다.


 인터페이스를 구현하면 Jsvc를 이용하여 실행이 가능하지만 경로 입력이 힘들고 커맨드로 Start / Stop / Restart 로직의 제어가 힘들기 때문에 일반적으로 쉘스크립트를 작성한다.


 스크립트에는 Jsvc 커맨드를 주어 실행시키고 .jar 파일을 연결하여 Parameter로 전달해주도록 한다. 자세한 스크립트는 다음 링크를 참조한다. (win100.tistory.com/120)


 명령어 설정을 이용하면 로그의 Redirection이 가능하다. 터미널이 없으므로 주로 파일로 redirect 한다.



 Java에서 모든 클래스의 부모 클래스인 Object 클래스는 toString을 비롯해 equals hashCode라는 메서드를 갖고 있다.

즉, 모든 클래스는 toString 과, equals, hashCode 를 갖고 있다고 볼 수 있으며 이는 자바 객체들의 특징이라고 할 수 있다.

여기에서 헷갈리는 부분이 equals와 hashCode 의 차이이며, 아래는 그 내용을 정리한 글이다.



 Equals는 두 객체의 내용이 같은지 동등성(equality)을 비교하며 hashCode는 두 객체가 같은 객체인지 동일성(identity)을 비교하는 역할을 한다.


 즉 hashCode를 사용하면 두 객체의 참조 비교를 하며 완전히 같은지를 판단한다.

 참고로 Java Map put 당시의 hashCode를 기록하므로 hashCode함수를 오버라이딩하여 구현할 시 중간에 값의 변경으로 hashCode가 변경되지 않도록 유의해야 한다.


 다음은 hashCode() 와 관련해서 정의된 규약이다.


-      equals()로 비교시 두개의 오브젝트가 같다면 hashCode() 값도 같아야 한다.


-      Equals()로 비교시 false라면 hashCode() 값은 같을수도 다를수도 있다. 성능을 위해서는 hashCode() 값이 다른 것이 낫다.


-      hashCode() 값이 같다고 해서 equals() true인 것은 아니다. 해싱 알고리즘 문제로 같은 해시값이 나올 수 있다.

 

: 다음은 equals() 와 관련된 규약이다.


-      Reflexive : Object는 그 자신과 항상 equals해야 한다.


-      Symmetric : a.equals(b) 일때 b.equals(a) 는 성립해야 한다.


-      Transitive : a.equals(b) 이고 b.equals(c) 라면 c.equals(a) 는 성립한다.


-      Consistent : equals의 호출은 객체가 변하지 않는 이상 항상 같은 결과를 반환해야 한다.


-      Null comparison : null과의 equals 비교는 NPE가 아닌 false를 반환해야 한다.



위 내용은 다음 블로그를 많이 참조 하였다. 

(http://anster.tistory.com/160, http://iilii.egloos.com/4000476)



+ Recent posts