다음은 Apache Commons Lang의 SerializationUtils를 사용한 자바 클론하는 예제이다.


public class SerializationUtilsTests {


  @Test

  public void testClone() {

    B b = new B("b1", "b2");

    A a = new A("a1", "a2", b);


    A clonedA = SerializationUtils.clone(a);


    assertThat(clonedA, is(not(sameInstance(a))));

    assertThat(clonedA.getA1(), is(a.getA1()));

    assertThat(clonedA.getA2(), is(a.getA2()));


    assertThat(clonedA.getB(), is(not(sameInstance(b))));

    assertThat(clonedA.getB().getB1(), is(b.getB1()));

    assertThat(clonedA.getB().getB2(), is(b.getB2()));

  }


  static class A implements Serializable {

    private String a1;

    private String a2;


    private B b;


    public A(String a1, String a2, B b) {

      this.a1 = a1;

      this.a2 = a2;

      this.b = b;

    }


    public String getA1() {

      return a1;

    }


    public void setA1(String a1) {

      this.a1 = a1;

    }


    public String getA2() {

      return a2;

    }


    public void setA2(String a2) {

      this.a2 = a2;

    }


    public B getB() {

      return b;

    }


    public void setB(B b) {

      this.b = b;

    }

  }


  static class B implements Serializable {

    private String b1;

    private String b2;


    public B(String b1, String b2) {

      this.b1 = b1;

      this.b2 = b2;

    }


    public String getB1() {

      return b1;

    }


    public void setB1(String b1) {

      this.b1 = b1;

    }


    public String getB2() {

      return b2;

    }


    public void setB2(String b2) {

      this.b2 = b2;

    }

  }


}


보는 바와 같이 deep copy한다.


static inner 클래스 (Class)가 아닌 inner 클래스 사용 시 다음과 같은 예외에 직면한다.


Caused by: java.io.NotSerializableException: samples.java.org.apache.commons.lang3.SerializationUtilsTests


당연히 테스트 클래스 자체를 Serializable로 만드는 것보다 static inner 클래스로 만드는 것이 바람직하겠다.


Reference:

http://stackoverflow.com/questions/4081858/about-java-cloneable

Posted by izeye

Lombok @Slf4j

자바/공부 2014.12.23 20:33

Lombok @Slf4j 애노테이션 (Annotation)을 활용하면,


다음과 같이 Logger 변수 log를 제거할 수 있다.


package samples.java.lombok.service;


import lombok.extern.slf4j.Slf4j;

//import org.slf4j.Logger;

//import org.slf4j.LoggerFactory;

import samples.java.lombok.domain.Person;


@Slf4j

public class DefaultPersonService implements PersonService {


//  Logger log = LoggerFactory.getLogger(getClass());


  @Override

  public void log(Person person) {

    log.debug("person: {}", person);

  }


}


Reference:

http://projectlombok.org/features/Log.html

Posted by izeye

자바에서 Long 값을 ==로 비교하면 안되지만,


실수하기 쉽다.


문제는 Long.valueOf()를 사용할 때


성능 향상을 위해 내부적으로 바이트 (Byte) 범위에 대해 캐시 (Cache)를 사용하는데


이로 인해 127을 넘어서기 전까지 정상 동작하는 함정이 있다.


다음은 이를 확인하는 테스트이다.


import org.junit.Test;


import static org.hamcrest.CoreMatchers.is;

import static org.hamcrest.CoreMatchers.not;

import static org.hamcrest.CoreMatchers.sameInstance;

import static org.hamcrest.MatcherAssert.assertThat;


public class LongTest {


    @Test

    public void valueOf() {

        assertThat(Long.valueOf("1"), is(sameInstance(Long.valueOf("1"))));

        assertThat(Long.valueOf("127"), is(sameInstance(Long.valueOf("127"))));

        assertThat(Long.valueOf("128"), is(not(sameInstance(Long.valueOf("128")))));

    }


}

Posted by izeye

메이븐 레포지토리 매니저인 아파치 Archiva Standalone 버전을 받아서 다음과 같이 구동한다.


./archiva console


다음과 같이 접속할 수 있다.


http://localhost:8080/


다음과 같이 artifact를 다운로드할 수도 있다.


http://localhost:8080/repository/internal/junit/junit/3.8.1/junit-3.8.1.jar


다음과 같이 artifact의 정보를 확인할 수도 있다.


http://localhost:8080/index.html#artifact/junit/junit


Reference:

http://archiva.apache.org/docs/2.1.1/quick-start.html

Posted by izeye

자바 8의 LocalDateTime과 구 Date 간의 상호 변환을 위해 다음과 같이 한다.


public class LocalDateTimeTest {


    @Test

    public void date2LocalDateTime() {

        Date date = new Date();

        System.out.println(date);

        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

        System.out.println(localDateTime);

    }


    @Test

    public void localDateTime2Date() {

        LocalDateTime localDateTime = LocalDateTime.now();

        System.out.println(localDateTime);

        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

        System.out.println(date);

    }


}


Date는 Time Zone 개념이 포함되어 있기 때문에


Time Zone 개념이 제거된 LocalDateTime으로 변환하기 위해 Time Zone을 알려줘야 하고,


그 역도 마찬가지 이유이다.


Reference:

http://stackoverflow.com/questions/19431234/converting-between-java-time-localdatetime-and-java-util-date

Posted by izeye

Logback에서 시간 기준 Rollover 시 해당 시간이 지나도 로그 이벤트가 발생하지 않는다면,


Rollover가 일어나지 않는다.


해결책으로는 해당 시간에 더미 (Dummy) 로그 이벤트를 발생시키는 방법이 있다.


더미 로그 이벤트를 발생시키는 것이 마음에 들지 않는다면,


다음과 같이 Appender의 rollover()를 직접 호출할 수도 있다.


@Component

public class LogbackRolloverHelper {


    private final Logger log = LoggerFactory.getLogger(getClass());


    @Scheduled(cron = "0 0 0 * * ?")

    public void rollover() {

        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

        for (ch.qos.logback.classic.Logger logger : loggerContext.getLoggerList()) {

            Iterator<Appender<ILoggingEvent>> appenderIterator = logger.iteratorForAppenders();

            while (appenderIterator.hasNext()) {

                Appender<ILoggingEvent> appender = appenderIterator.next();

                if (appender instanceof RollingFileAppender) {

                    RollingFileAppender rollingFileAppender = (RollingFileAppender) appender;

                    TriggeringPolicy triggeringPolicy = rollingFileAppender.getTriggeringPolicy();

                    if (triggeringPolicy instanceof TimeBasedRollingPolicy) {

                        if (triggeringPolicy.isTriggeringEvent(null, null)) {

                            rollingFileAppender.rollover();

                            log.debug("Tried to force to rollover log file for the appender '" + rollingFileAppender + "'.");

                        }

                    }

                }

            }

        }

    }


}


Reference:

http://stackoverflow.com/questions/22188936/timebasedrollingpolicy-not-rolling-unless-there-are-new-logs

Posted by izeye

자바 8에서 인터페이스 (Interface)에 디폴트 메소드와 정적 메소드가 추가되었다.


다음은 이를 테스트하는 예제 (Example)이다.


import org.junit.Test;


public class DefaultMethodTest {


    static interface InterfaceA {

        String getSomething();


        void useStatic();


        void useDefault();


        static void doSomethingInStatic() {

            System.out.println("Doing something...");

        }


        default void doSomethingInDefault() {

            System.out.println("Doing something with " + getSomething() + "...");

        }

    }


    static class ClassA implements InterfaceA {

        @Override

        public String getSomething() {

            return "something";

        }


        @Override

        public void useStatic() {

//            doSomethingInStatic();

            InterfaceA.doSomethingInStatic();

        }


        @Override

        public void useDefault() {

            doSomethingInDefault();

        }

    }


    @Test

    public void test() {

        ClassA a = new ClassA();

        InterfaceA.doSomethingInStatic();

//        a.doSomethingInStatic();

        a.doSomethingInDefault();


        a.useStatic();


        a.useDefault();

    }


}


정적 메소드는 인터페이스 이름으로만 접근할 수 있다.


인터페이스 타입의 객체를 통해서도 접근할 수 없다.


따라서 정적 메소드는 유틸리티 메소드에 적합하다.


객체 내에서 인터페이스 이름 없이 정의하고자 하는 메소드를 직접 사용하거나,


정의하고자 하는 메소드 내에서 객체를 참조한다면,


디폴트 메소드로 작성해야만 한다.


-----


다음은 디폴트 메소드에 대한 다중 상속 (Multiple Inheritance) 테스트이다.


import org.junit.Test;


public class DefaultMethodMultipleInheritanceTest {


    static interface InterfaceA {

        default void doSomething() {

            System.out.println("InterfaceA");

        }

    }


    static interface InterfaceB {

        default void doSomething() {

            System.out.println("InterfaceB");

        }

    }


//    static class ClassA implements InterfaceA, InterfaceB {

    static class ClassA implements InterfaceA {

        public void test() {

            doSomething();

        }

    }


    @Test

    public void test() {

        ClassA a = new ClassA();

        a.test();

    }


}


혹시나 해서 시도해봤지만, 컴파일 에러가 발생했다.


Reference:

http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Posted by izeye

자바 JIT 컴파일 로그를 확인하기 위해 다음 VM 옵션을 사용할 수 있다.


-XX:+PrintCompilation

Posted by izeye

리눅스에서 자바 쓰레드의 PID를 확인하기 위해 다음과 같이 할 수 있다.


ps -T | grep java


하지만 자바 쓰레드에 대한 상세 정보는 얻을 수 없다.


다음 명령으로 확인할 수 있다.


jstack <PID>


각 쓰레드의 nid 값이 16진수 PID 값이다.


참고로 개별 쓰레드를 죽일 수 있는 방법은 없다.


개별 쓰레드의 PID로 kill하면, 프로세스 (Process)가 죽는다.


References:

http://stackoverflow.com/questions/4764167/inspecting-java-threads-in-linux-using-top

http://unix.stackexchange.com/questions/1066/how-can-i-kill-a-particular-thread-of-a-process

Posted by izeye

Jedis에서 Redis로 set 시 expiration time을 설정하기 위해 다음과 같이 할 수 있다.


public class JedisTest {


    @Test

    public void test() {

        String key = "foo";

        String value = "bar";


        Jedis jedis = new Jedis("localhost");


        jedis.set(key, value);


        value = jedis.get(key);

        System.out.println(value);


        jedis.expire(key, 5);


        value = jedis.get(key);

        System.out.println(value);


        try {

            Thread.sleep(5000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }


        value = jedis.get(key);

        System.out.println(value);


        value = "bar2";


        jedis.setex(key, 5, value);


        value = jedis.get(key);

        System.out.println(value);


        try {

            Thread.sleep(5000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }


        value = jedis.get(key);

        System.out.println(value);

    }


}


첫번째 방법은 set() 한 뒤에 expire()하는 방식이고,


두번째 방법은 동시에 하는 방식이다.


References:

https://github.com/xetorthio/jedis

http://stackoverflow.com/questions/26339277/why-is-the-nxxx-parameter-of-set-in-jedis-exclusive

Posted by izeye


티스토리 툴바