StackOverlow 의 아래 답변을 참고하자.

http://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java


정리하면, JVM은 main thread가 끝나더라도, 아직 수행중인 다른 thread - non daemon thread(user thread) - 가 있다면, 중지되지 않는다.

즉, process가 계속해서 돈다.

C/C++ 처럼, main thread가 exit될 때 process를 종료시키려면, 모든 child thread 속성을 daemon thread로 설정해야 한다.


Thread t = new Thread(...)

t.setDaemon(true);


남아 있는 모든 thread가 Daemon thread일 경우, JVM은 중지된다.

다만, 이런식으로 thread가 급작스레 종료하는 것은 상당히 불안정한 결과를 가져 올 수 있으므로 주의해야 한다.


다시 말하면, 단 하나라도 종료되지 않은 user thread (non-daemon thread) 가 존재할 경우, JVM은 종료되지 않고, 모든 다른 thread (Daemon thraed 포함)역시 계속해도 수행된다.



Java에서는 selective compile이 되지 않는다.

대신, compile time에 결정되는 것들을 이용해서 selective compile과 비슷한 효과를  만들어 낼 수 있다.

예를 들면,


Config.jar
----------
class Config {
...
    public static final boolean DEBUG = false;
...
}


Main.java
---------
...
if (Config.DEBUG) System.out.println("debug line...");
...

자, 그러면 어디서 어디까지 Compile time 에 결정되는가?

openJDK 1.6에서 test를 해 보면, 아래의 것들에 대해서는 compile time에 결정되는다는 것을 확인했다.


primitive types (int, boolean, long...) + String.


여기서 의외의 부분이 'String'인데...

실제, 아래와 같이 static final String 변수로 test해 보면, 이것을 확인할 수 있다.

Config.jar
----------
class Config {
    ...
    public static final String MODE = "debug";
    ...
}


Main.java
---------
...
if (Config.MODE.equals("debug")) System.out.println("debug mode...");
...

생각해보면, String class자체가 constant class이므로 - 한번 생성되면, 내용이 바뀌지 않는 class - 위와 같은 compile time check가 가능하지 않을까... 생각이 든다.


아래는 위의 내용에 대한 상세 test이다.

test/lib/Config.java -------------------- package test.lib; public class Config { public static final int TEST_INT_0 = 1; public static final boolean TEST_BOOL_0 = false; public static final String TEST_STR_0 = "test-str-0"; public static int TESTV_INT_0 = 1; public static boolean TESTV_BOOL_0 = false; public static String TESTV_STR_0 = "test-str-0"; } ===> export to 'test0.jar' package test.lib; public class Config { public static final int TEST_INT_0 = 10; public static final boolean TEST_BOOL_0 = true; public static final String TEST_STR_0 = "test-str-1"; public static int TESTV_INT_0 = 10; public static boolean TESTV_BOOL_0 = true; public static String TESTV_STR_0 = "test-str-1"; } ===> export to 'test1'jar Main.java ---------- import test.lib.Config; public class Main { public static void main(String[] args) { if (Config.TEST_STR_0.equals("test-str-0")) System.out.println("Config:TEST_STR_0 : IF path - test-str-0"); else System.out.println("Config:TEST_STR_0 : ELSE path - test-str-0"); if (Config.TEST_INT_0 > 5) System.out.println("Config:TEST_INT_0 : IF path - > 5"); else System.out.println("Config:TEST_INT_0 : ELSE path - > 5"); if (Config.TEST_BOOL_0) System.out.println("Config:TEST_BOOL_0 : IF path - true"); else System.out.println("Config:TEST_BOOL_0 : ELSE path - "); if (Config.TESTV_STR_0.equals("test-str-0")) System.out.println("Config:TESTV_STR_0 : IF path - test-str-0"); else System.out.println("Config:TESTV_STR_0 : ELSE path - test-str-0"); if (Config.TESTV_INT_0 > 5) System.out.println("Config:TESTV_INT_0 : IF path - > 5"); else System.out.println("Config:TESTV_INT_0 : ELSE path - > 5"); if (Config.TESTV_BOOL_0) System.out.println("Config:TESTV_BOOL_0 : IF path - true"); else System.out.println("Config:TESTV_BOOL_0 : ELSE path - "); } } ========================================== $ javac -classpath test0.jar Main.java $ java -classpath .:test0.jar Main Config:TEST_STR_0 : IF path - test-str-0 Config:TEST_INT_0 : ELSE path - > 5 Config:TEST_BOOL_0 : ELSE path - true Config:TESTV_STR_0 : IF path - test-str-0 Config:TESTV_INT_0 : ELSE path - > 5 Config:TESTV_BOOL_0 : ELSE path - true $ $ java -classpath .:test1.jar Main Config:TEST_STR_0 : IF path - test-str-0 <--- 바뀌지 않음. (변수 값이 compile time에 이미 binding되어 있음.) Config:TEST_INT_0 : ELSE path - > 5 <--- 상동 Config:TEST_BOOL_0 : ELSE path - true <--- 상동 Config:TESTV_STR_0 : ELSE path - test-str-0 Config:TESTV_INT_0 : IF path - > 5 Config:TESTV_BOOL_0 : IF path - 참고 : TESTV_XXX_0를 없애면, test0.jar 혹은 test1. jar를 'java'의 'classpath' 에 명시해 주지 않더라도 정상수행 된다. ex. $ java Main 왜냐하면, 이미 모든 code가 compile time에 binding어 있는 상태으므로, Runtime에는 더 이상 'test.lib.Config' 를 참조하지 않기 때문이다.

위와 같은 static final 변수를 runtime binding하기 위한 방법의 한 예로 reflection을 들 수 있다.

reflection을 이용해서 해당 변수 field를 접근하면, static final로 선언된 변수이지만, runtime binding이 가능하다.

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class Main {
    private static volatile int sCnt = 0;
    private static class TestRun implements Runnable {
        @Override
        public void
        run() {
            int num = sCnt++;
            System.out.println("Run(" + num + ") - Start");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ignored) { }
            System.out.println("Run(" + num + ") - End");
        }
    };
    public static void
    main(String[] args) {
        ThreadPoolExecutor tpe = new ThreadPoolExecutor
                (2,
                 2,
                 Long.MAX_VALUE,
                 TimeUnit.MILLISECONDS,
                 new LinkedBlockingQueue());
        int num = 10;
        while (0 < num--)
            tpe.execute(new TestRun());
    }
}

Java visibility는 private, protected, default(package private), public 이렇게 4단계가 있다.
그런데 개인적으로 한단계 정도 더 있었으면 한다.

기능별로 block을 형성하도록 programming할 수 있어야 한다. 그게 oop의 기본이기도 하다.
하나의 class가 하나의 block을 형성할 수 있으면 좋겠지만, 보통 여러개의 class가 하나의 기능 block을 형성한다.
그리고, 이 기능 block의 내부 interface는 package private으로 하고, 외부 interface는 public으로 둔다.
이게 Java에서의 일반적인 programming방법이다.
그런데, 어떤 기능 block 자체가 더 큰 기능 block의 한 부분이게 하고 싶은 경우는 어떻게 해야 하는가?
물론, 재 사용성을 위해서 모든 기능 블럭은 자체적으로 완벽하게 동작하도록 디자인하고, 관련 interface는 public으로 해 둘 수 있게 하는것이 이상적이긴 하다.
그렇지만, 대부분의 경우, 큰 기능 블럭의 한 부분임을 가정하고 programming하는 경우가 많다.
왜냐하면, 일반적인 기능블럭(public interface를 가지는...)을 만들어 내기 위해서는 추가적인 많은 노력들이 필요하기 때문이다.
그런데, Java의 visibility는 이런 경우를 해결해 줄 수 없다.
(하나의 package로 구성된 기능 block의 interface는 public이여야만 한다.)
그래서 개인적으로 추가적인 안을 제시해 본다.

*** tree-based name space ***

name space가 tree형태를 가진다. java convention을 이용해 설명하면, '.'을 separator로 하고, 각 name이 tree의 path를 의미하도록 하는 것이다.
예를 들면, 'com.java.io'라면, 'java'는 'com'의 child 이고, 'io'는 'java'의 child가 된다.

***  parent private ***

visibility가 자신의 parent에게만 되도록...

음.. visibility가 자꾸 많아지는 것도 안 좋긴 한데... 일단 이런게 있었으면 좋겠다... 단점도 있을 것 같은데.. 좀더 고민해 보자...

⚫ From VM Spec

⚬ In particular, x != x is true if and only if x is NaN, and (x<y) == !(x>=y) will be false if x or y is NaN.
⚬ round towards zero
⚬ Multibyte data items are always stored in big-endian order.

⚫ Java VM Type Signature

Signature        Java Type
Z                             boolean
B                             byte
C                             char
S                             short
I                             int
J                             long
F                             float
D                             double
L fully-qualified-class ;     fully-qualified-class
[ type                        type[]
( arg-types ) ret-type        method type

to be continue ...

* Following codes is to change byte[] to integer-typed-value and vice versa.
=> Note : JavaVM uses Big-Endian. And, size of each integer-type is byte(1), short(2), int(4), long(8).

public static final int
byteArrayToLongBE(byte[] b) {
    return ((b[0]&0xff) << 56) + ((b[1]&0xff) << 48)
         + ((b[2]&0xff) << 40) + ((b[3]&0xff) << 32)
         + ((b[4]&0xff) << 24) + ((b[5]&0xff) << 16)
         + ((b[6]&0xff) << 8)  + (b[7]&0xff);
}

public static final int
byteArrayToLongLE(byte[] b) {
    return (b[0]&0xff          + ((b[1]&0xff) << 8)
         + ((b[2]&0xff) << 16) + ((b[3]&0xff) << 24)
         + ((b[4]&0xff) << 32) + ((b[5]&0xff) << 40)
         + ((b[6]&0xff) << 48) + ((b[7]&0xff) << 56));
}

public static final int
byteArrayToIntBE(byte[] b) {
    return ((b[0]&0xff) << 24) + ((b[1]&0xff) << 16)
         + ((b[2]&0xff) << 8) + (b[3]&0xff);
}

public static final int
byteArrayToIntLE(byte[] b) {
    return (b[0]&0xff) + ((b[1]&0xff) << 8)
         + ((b[2]&0xff) << 16) + ((b[3]&0xff) << 24);
}

public static final short
byteArrayToShortBE(byte[] b) {
    return (short) (((b[0]&0xff) << 8) + (b[1]&0xff));
}

public static final short
byteArrayToShortLE(byte[] b) {
    return (short) ((b[0]&0xff) + ((b[1]&0xff) << 8));
}

public static final byte[]
longToByteArrayBE(long v) {
    return new byte[] {
            (byte)(v >>> 56), (byte)(v >>> 48),
            (byte)(v >>> 40), (byte)(v >>> 32),
            (byte)(v >>> 24), (byte)(v >>> 16),
            (byte)(v >>> 8),  (byte)v};
}

public static final byte[]
longToByteArrayLE(long v) {
    return new byte[] {
            (byte)v,          (byte)(v >>> 8),
            (byte)(v >>> 16), (byte)(v >>> 24),
            (byte)(v >>> 32), (byte)(v >>> 40),
            (byte)(v >>> 48), (byte)(v >>> 56)};
}

public static final byte[]
intToByteArrayBE(int v) {
    return new byte[] {
            (byte)(v >>> 24), (byte)(v >>> 16),
            (byte)(v >>> 8),  (byte)v};
}

public static final byte[]
intToByteArrayLE(int v) {
    return new byte[] {
            (byte)v,          (byte)(v >>> 8),
            (byte)(v >>> 16), (byte)(v >>> 24)};
}

public static final byte[]
shortToByteArrayBE(short v) {
    return new byte[] {(byte)(v >>> 8), (byte)v };
}

public static final byte[]
shortToByteArrayLE(short v) {
    return new byte[] {(byte)v, (byte)(v >>> 8) };
}

* Run process

// Recommanded
// Run shell command and return it's output as string
public static String
runCmd(String... cmd) {
    String r = "";
    try {
        // execute command
        ProcessBuilder pb = new ProcessBuilder(cmds);
        // pb.redirectErrorStream(true); // if needed.
        // wait till running is done.
        Process pr = pb.start();
        pr.waitFor() ;
        String line;
        // Reader output of sub process.
        BufferedReader br = new BufferedReader(new InputStreamReader(pr.getInputStream())) ;
        // Make output String object
        while ( null != (line = br.readLine()) ) r += line + "\n";
    } catch (Exception e) {
        ; // Exception Handling!
    }
    return r;
}

// OR
public static String
    runCmd(String[] cmds) {
    String r = "";
    try {
        // execute command
        Process pr = Runtime.getRuntime().exec(cmds) ;
        // wait till running is done.
        pr.waitFor() ;
        // Reader output of sub process.
        BufferedReader br = new BufferedReader(new InputStreamReader(pr.getInputStream())) ;
        // Make output String object
        String  line;
        while ( null != (line = br.readLine()) ) r += line + "\n";
    } catch (Exception e) {
        ; // Exception Handling!
    }
    return r;
}

* Run shell command

// We should invoke SHELL (not process command directly)
// See above for 'runCmd'
String cmd = "ls -al | grep text";
runCmd("/bin/bash", "-c", cmd);
// or : runCmd(new String[]{"/bin/bash", "-c", cmd});

* Multi-lined JLabel : We can do this by using HTML directly.

JLabel jl = new JLabel("<html>1st line<br>2nd line</html>");

* Loading java property

Properties prop = new Properties();
try {
    prop.load(new FileInputStream(property_file_path));
} catch (IOException e) {
    ; // exception handling
}

* String to Integer

try {
    int v = Integer.parseInt("3456");
} catch (NumberFormatException e) {
    ; // exception handling
}

=== to be continued...

'Language > Java' 카테고리의 다른 글

[Java][Test Code] ThreadPoolExecutor...  (0) 2013.09.25
[Java] Visibility에서 추가했으면 하는 것....  (0) 2011.04.21
[Java] Some notable stuffs of VM  (0) 2011.01.06
[Java] Package private in Java  (0) 2009.11.16
[Java][Tips] Compile...  (0) 2009.10.18
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Java has useful visibility; package private.
Let's see the following case.

We want implement quite big module A. And this has some sub features. So, we need to make sub classes a, b, c.

In this case, external module should be able to see only interfaces of A; Not those of a, b and c. It is very difficult to make this in C++. But, in java, we can use package private. Here is design example.

Put all these modules in the same package.
Make interfaces of A as public.
Make all interfaces of a, b and c be package private.

Developer can easily know that using a, b and c directly is not allowed intuitively.

How about in C++?
In C++, there is no proper way to do this. Making A be 'friend' of a, b and c, breaks encapsulation. Making interfaces of a, b and c be public, may lead to misuse of those; we want only interfaces of A be visible to external.

I has been desired this kind of visibility - ex. namespace private - when using C++. :-)

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]] 

Java also uses compiler. So, if we meet with compile error, we need to check compile option.

[Cases]
Error : "Access restriction : the field ..." [in Eclipse]

'Project' -> 'Properties' -> 'Java Compiler' -> 'Errors/Warnings' -> 'Deprecated and restricted API' -> Forbidden reference (access rule) -> change from 'Error' to 'Warning'.
=> We can make compile success. But, please keep it mind... using forbidden reference is not recommended!!

Using external Jar [in Eclipse]

Right click on Project -> Properties -> select 'Java Build Path' -> select 'Libraries' tab -> select 'Add External JARs' button...

+ Recent posts