고민 후 괜찮다고 판단할 때만 기본 직렬화 형태 사용하기 유연성 , 성능, 정확성 측면에서 신중히 고민 후 합당할 때만 사용 이상적인 직렬화 상태 : 객체의 물리적 표현(코드로 어떻게 구현했는지)과 논리적 내용(실제로 의미하는 것)이 같다면 기본 직렬화 형태여도 무방함 //기본 직렬화 형태에 적합 public class Name implements Serializable { private final Stirng lastName; private final String firstName; private final String middleName; } 기본 직렬화 형태가 적합하더라도 불변식 보장과 보안을 위해 readObject 메서드를 제공해야 할 때가 많음. 위의 예시에서 lastName, firstNam..
Serializable Serializable 인터페이스의 구현 클래스는 인스턴스를 직렬화할 수 있다. Serializable 구현은 아주 값비싼 일 Serializable 구현 후 릴리스한 뒤에는 수정이 어려움 직렬화 형태도 하나의 공개 API가 되어 영원히 지원해야함 자바의 기본 직렬화 형태에서는 클래스의 private, protected 필드들도 API로 공개되어 캡슐화가 깨짐 뒤늦게 클래스 내부 구현을 손보면 원래의 직렬화 형태와 달라지게되어 안됨 직렬화 가능 클래스를 만들고자 한다면 고품질의 직렬화 형태도 주의해서 함께 설계해야함 [아이템 87,90] 모든 직렬화된 클래스는 고유 식별 번호를 부여받고 (serialVersionUID라는 static final long 필드), 이 번호를 명시하지..
직렬화 java.io.Serializable 인터페이스를 상속받은 객체를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술 직렬화의 문제는 공격범위가 너무 넓고 지속적으로 더 넓어져 방어하기 어렵다는 점 (객체를 역직렬화할 수 있어서 공격에 위험함) 역직렬화 : 직렬화와 반대로 byte로 변환된 데이터를 객체로 변환하는 기술 자바의 표준 라이브러리, 서드파티 라이브러리, 애플리케이션 자신의 클래스들 모두 공격범위에 포함된다. 가젯 보안 전문가들이 찾은 자바 라이브러리와 서드파티 라이브러리에서 직렬화 가능 타입들을 연구하여 역직렬화 과정에서 호출되어 잠재적으로 위험한 동작을 수행하는 메서드들 여러 가젯을 사용하여 네이티브 코드를 마음대로 실행하는 공격을 하기도 함 → 아주 ..
스레드 스케줄러 여러 스레드가 실행중이면 운영체제의 스레드 스케줄러가 어떤 스레드를 얼마나 오래 실행할지 정한다. 운영체제는 모두 공정하게 수행하지만 구체적인 운영정책은 운영체제마다 다를 수 있다. 이 정책에 좌지우지 되지 않아야 좋은 프로그램이다. 정확성이나 성능이 스레드 스케줄러에 따라 달라지는 프로그램은 다른 플랫폼에 이식하기 어렵다. 실행 가능한 스레드 수를 적게 유지하는 방법 실행 가능한 스레드의 평균적인 수를 프로세서 수보다 지나치게 많아지지 않도록 해야한다. 1) 스레드는 당장 처리해야할 작업이 없다면 실행돼서는 안된다. 스레드 풀 크기를 적절히 설정하고 작업은 짧게 유지해야하나, 너무 짧으면 오히려 분배 부담이 늘어나 성능이 떨어진다. 바쁜 대기(busy waiting) 상태가 되면 안된다..
지연 초기화 (lazy initialization) 필드 초기화 시점을 그 값이 처음 필요할 때 까지 늦추는 기법 정적 필드와 인스턴스 필드에 모두 사용 가능 주로 최적화 용도지만, 클래스와 인스턴스 초기화 때 발생하는 위험한 순환 문제를 해결하는 효과도 있음 지연 초기화는 필요할 때까지는 하지 말라 클래스나 인스턴스 생성 시 초기화 비용은 줄지만, 지연 초기화하는 필드에 접근하는 비용은 커짐 지연 초기화하려는 필드들 중 초기화가 이루어지는 비율에 따라, 실제 초기화 비용에 따라, 초기화 된 각 필드를 얼마나 빈번히 호출하느냐에 따라 지연 초기화가 성능이 느려지게 할 수도 있음 지연 초기화가 필요할 때 해당 클래스의 인스턴스 중 그 필드를 사용하는 인스턴스의 비율 < 그 필드 초기화 비용 일 때 정말 그..
스레드 안전성 한 메서드를 여러 스레드가 동시에 호출할 때 그 메서드가 어떻게 동작하는 지는 해당 클래스와 사용자와의 중요한 계약이다. 메서드 선언에 synchronized 한정자를 선언할지는 구현 이슈일 뿐 API에 속하지 않음 그래서 그것만으로 스레드 안전하다고는 할 수 없음 멀티스레드 환경에서도 API를 안전하게 사용하게 하려면 클래스가 지원하는 스레드 안전성 수준을 정확히 명시해야함 스레드 안전성이 높은 순 불변(immutable) : 이 클래스의 인스턴스는 마치 상수같아서 외부 동기화도 필요 없음. ex) String, Long, BigInteger [아이템 7] 무조건적 스레드 안전 : 이 클래스의 인스턴스는 수정될 수 있으나 내부에서 잘 동기화하여 외부 동기화 없이 동시에 사용해도 안전하다...
1. 객체지향의 사실과 오해 객체지향의 사실과 오해 『객체지향의 사실과 오해』는 객체지향이란 무엇인가라는 원론적면서도 다소 위험한 질문에 답하기 위해 쓰여진 책이다. 안타깝게도 많은 사람들이 객체지향의 본질을 오해하고 있다. 가장 널리 퍼져있는 오해는 클래스가 객체지향 프로그래밍의 중심이라는 것이다. 객체지향으로 향하는 첫 걸음은 클래스가 아니라 객체를 바라보는 것에서부터 시작한다. 객체지향으로 향하는 두 번째 걸음은 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 바라보는 것이다. 세 번째 걸음을 내디딜 수 있는지 여부는 협력에 참여하는 객체들에게 얼마나 적절한 역할과 책임을 부여할 수 있느냐에 달려 있다. 객체지향의 마지막 걸음은 앞에서 설명한 개념들을 프로그래밍 언어라..
동시성 유틸리티 자바5에 도입된 고수준의 동시성 유틸리티 덕분에 자바의 wait와 notify [아이템 50] 를 사용해야 할 이유가 줄었다. wait와 notify는 올바르게 사용하기 까다로우니 고수준 동시성 유틸리티를 사용하자. java.util.concurrent의 고수준 유틸리티의 범주 : 실행자 프레임워크 [아이템 80], 동시성 컬렉션(concurrent collection), 동기화 장치(sychronized) 동시성 컬렉션 표준 컬렉션 인터페이스에 동시성을 가미해 구현한 고성능 컬렉션 높은 동시성을 위해 동기화를 각자 내부에서 수행 [아이템 79] 동시성 컬렉션에서 동시성을 무력화하는 것은 불가능, 외부에서 락을 추가로 사용하면 오히려 속도가 느려짐 동시성 무력화가 불가능하므로 여러 메서드..
java.util.concurrent 아이템 49에서 백그라운드 스레드에 위임해 비동기적으로 작업을 요청해 처리하는 작업 큐를 생성해 사용했었다. 이제는 직접 사용자가 작업 큐를 작성하지 않고 java.util.concurrent 패키지를 사용하면 된다. 실행자 프레임워크라고 하는 인터페이스 기반의 유연한 태스크 실행 기능을 담고 있다. ExecutorService exec = Executors.newSingleThreadExecutor(); //실행자 생성 exec.execute(runnable); //실행 할 태스크를 넘기는 방법 exec.shutdown(); //실행자를 종료시키는 방법 ExecutorService(실행자 서비스)의 주요 기능들 큐에 작업을 제출하고서 작업이 완료될 때까지 기다릴 수..
과도한 동기화 과도한 동기화는 성능 저하, 교착상태, 예측할 수 없는 동작을 야기한다. 응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 안에서는 제어를 절대로 클라이언트에게 양도하면 안됨 예를 들어, 동기화된 영역 안에서는 재정의할 수 있는 메서드를 호출하거나 클라이언트가 넘겨준 함수 객체 [아이템 24]를 호출해서도 안됨 이런 외계인 메서드에서는 무엇을 할 지 알지 못하고 통제할 수도 없음 과도한 동기화 예제 Observer Pattern 으로 구현한 Set Observer Pattern : 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 클라이언트는..