발생되는 경우 지역변수인 변수명의 변수가 초기화가 되어있지 않았을 경우
조 언 지역변수(메소드 내에서 선언한 변수)를 초기화 하지 않은채 선언했을 경우 발생한다.
멤버 필드가 아닌 경우는 반드시 변수 선언시 초기화를 해주어야 한다.
(멤버 필드는 자바 프로그램 자체에서 자동으로 default값으로 초기화 해준다.)
자바 위키 -http://ko.wikipedia.org/wiki/자바
발생되는 경우 지역변수인 변수명의 변수가 초기화가 되어있지 않았을 경우
조 언 지역변수(메소드 내에서 선언한 변수)를 초기화 하지 않은채 선언했을 경우 발생한다.
멤버 필드가 아닌 경우는 반드시 변수 선언시 초기화를 해주어야 한다.
(멤버 필드는 자바 프로그램 자체에서 자동으로 default값으로 초기화 해준다.)
발생되는 경우 static 메소드 안에서 static 으로 선언되지 않은 메소드나 변수를 참조(사용)했을 경우.
특히, 메소드의 경우는 인스턴스를 사용하지 않고 static메소드 내에서 바로 선언한 경우.
조 언 static 선언자의 사용여부를 살펴보고 static 메소드 안에 static으로 선언되어지지 않은 메소드나 변수가 있느지 확인해본다.
만약 그런것이 있으면 메소드를 새로 만들어 그쪽에서 선언한다. 단, 인스턴스를 생성해서 불러줘야 한다는 것을 잊지 말아야한다.
symbol : class in(에러가 난 부분)
location : class StackTest(찾으려는 위치)
발생되는 경우 이해할 수 없는 클래스나 메소드, 변수명이 올경우
조 언 보통 이 에러는 철자가 틀렸을 경우에 많이 발생한다. 클래스, 메소드, 변수의 철자를 세심히 확인해 본다.
특히, 철자를 확인할때 대소문자 구분을 확실히 체크한다.(자바는 대소문자를 구별한다.) 그리고 클래스에서 발생할 경우 import를 해주었는지 확인해 봅니다.
발생되는 경우 클래스 파일을 찾을 수 없는 경우
조 언 실행하려는 클래스 파일 이름이 제대로 되어 있는지 확인한다.
또한, CLASSPATH 설정이 제대로 되어 있는지 확인하며 (도스모드에서 set명령어)
만약, 되어있지 않다면 설정한다. (CLASSPATH = jdk1.3/jre/lib/rt.jar; 2-1강좌 참조)
InterruptedException 이란??
말 그대로 Thread가 중단되었을 때 발생하는 예외입니다. 즉, wait()메소드나 sleep() 메소드를
사용해 Thread가 대기 상태로 들어갔다가 깨어나지 못 할때 발생하는 예외입니다. 또한,
interrupt()메소드를 사용해 Thread를 중단시킬 때 발생하기도 합니다. 자세한 내용
은 InterruptedException class의 소스 파일을 보여 드리죠. JAVA는 항상 궁금한 것이 있을
때 소스 파일을 뒤져보면 얻게 되는것이 많을 겁니다..
GSON
GSON은 Java <–> JSON 변환을 아주 쉽게 가능하도록 도와주는 자바 라이브러리다.
GSON을 사용해서 코드를 작성하면 이기종 호환성, 유지보수에 꽤나 도움이 된다.
주요 스펙
생성
private static final Gson gson = new Gson();
매번 new를 할 필요 없다, 하나의 Gson객체면 충분하다. gson객체는 공유 가능하다.
형 변환
Java -> JSON
gson.toJson(short,int,long,float,double,String,Object);
JSON -> Java
gson.fromJson(JSON문자, JavaClass.class); // 예를 들어, gson.fromJson(jsonStr, int.class);
제네릭 변환
Java -> JSON
gson.toJSON(Generic); // 예를 들어, List<MyClass> list;
JSON -> Java
gson.fromJson(JSON문자열, new TypeToken<제네릭타입>() {}.getType());
예를 들어, gson.fromJson(JSON문자열, new TypeToken<List<MyClass>>() {}.getType());
—– 추가
안드로이드 어플리케이션을 개발하다 보면 주소록을 다루는 일이 종종 있습니다. 어플리케이션에서 주소록에 관련된 정보를 접근할 일이 있는 어플이라면 ContentResolver를 통해 단말의 주소록에 접근해서 필요한 정보를 가져오게 됩니다.
그런데, 최근 개발하고 있는 스포카 어플을 통해 아주 많은 사람의 연락처가 저장된 주소록을 가지고 이런 저런 로직을 실행하는 상황을 테스트 하다보니, OutOfMemory(OOM)에러가 발생하는 현상을 볼 수 있었습니다. 모바일 디바이스들은 PC와 다르게 자원이 제한적이기 때문에 어떻게 하면 OOM을 일으키지 않을 수 있을까 라는 고민을 해야 하는 상황이었습니다.
대강 문제가 되었던 클라이언트 사이드의 로직을 살펴보면 이렇습니다.
eclipse의 MAT(Memory Analyzer)을 이용하여 어느 시점에서 OOM이 일어나는지를 추측해보았습니다. 서버에서 보내준 json형식의 문자열을 HttpURLConnection을 통해 전달받고 이를 StringBuilder를 이용하여 완전한 문자열으로 만들던 도중에 OOM이 일어나는 것으로 의심되었는데 이 때문에 JSONObject의 생성자에 json 문자열을 전달하기도 전에 메모리가 가득 차 버리니 매우 난감한 상황이었습니다.
대게 주소록에 사람이 그렇게 많지 않으므로 (200~500명 정도) 아무런 문제가 없었지만 10000명 정도의 더미데이터를 주소록에 저장하고 테스트하다 보니 append 메서드를 호출하다 OOM에러를 뱉으면서 어플이 종료되었습니다. 문제는 append 메서드를 호출 시 StringBuilder의 capacity를 넘을 경우 내부적으로는 메모리 재할당과 copy과정이 일어난다는 것이었습니다. 그렇다고 초기 StringBuilder생성시 capacity를 무작정 높게 잡기도 애매한 상황이었습니다.
gson은 Java객체를 json형식으로 변환하고 그 역으로도 변환할 수 있도록 도와주는 라이브러리입니다. gson의 사용법이 궁금하다면 gson user guide를 읽어보면 되고 api가 궁금하다면 gson api document를 참조하면 됩니다.
대략 이런 방식으로 프로젝트에 gson라이브러리를 적용하였고, HttpURLConnection을 통해 받아온 InputStream을 이용 바로 객체를 생성할 수 있었습니다. 이전에 StringBuilder를 이용할때 생기는 오버헤드가 사라진 셈이죠. 위와 같은 방식으로 OOM이 생기는 문제 상황을 해결 할 수 있었습니다.
위의 예는 상황을 최대한 단순화하여 설명하려고 작성한 예제이고 이 사이트를 통해 더 상세하게 설명된 사용예를 보실 수 있습니다.
json라이브러리중에 GSON 라이브러리를 사용해서 Array 형태의 JSON String을 ArrayList<Object> 형태로 자동 변환을 해보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
[ { title: '초보를 위한 Java' , author: '홍길동' , isbn : 'A000022200f' } , { title: 'Java 개발자' , author: '이몽룡' , isbn : 'A1111100ff0' } ] |
1
2
3
4
5
|
class Book { private String title; private String author; private String isbn; } |
1
2
3
4
5
|
Gson gson = new Gson(); Type type = new TypeToken<list<book>>() {}.getType(); List<book> bookList = gson.fromJson(jsonString, type); </book></list<book> |
1. GSON
GSON는 json 형태를 자바 객체로 변환하는데 사용할 수 있도록 구글에서 제공한 자바 라이브러리 입니다.
현재 Google Gson Version 2.2.4 버전을 다운로드 받으실 수 있습니다.
기본적으로 주로 Gson 클래스를 사용하고, new Gson() 으로 객체를 생성할 수 있습니다. 다양한 설정을 위해서 GsonBuilder 클래스를 사용합니다.
– json string -> java object
아래와 같은 형태의 json string을 java 객체에 매핑하는 방법입니다. gson 객체의 fromJson() 메서드를 사용하여 쉽게 매핑할 수 있습니다.
{ “name”:”홍길동”, “age”:”25″, “favoriteFood”:[“김치볶음밥”, “부대찌개”, “비빔밥”], “etc”:{“email”:”abc@naver.com“, “address”:”xxx”} }
– java object -> json string
아래의 예제는 Map 객체를 json 형태로 변환하는 소스입니다. 위의 소스와 마찬가지로 gson 객체를 생성 후 toJson() 메서드를 사용하여 Map객체를 json 형태로 변환하였습니다.
2. JACKSON
Jackson 또한 GSON과 마찬가지로 json 형태를 자바 객체로, 자바 객체를 json 형태로 변환해주는 자바 라이브러리 입니다.
현재 latest version is 2.2.3 버전을 다운로드 받으실 수 있습니다.
Jackson은 다음과 같이 JSON을 처리하는 위한 3가지 방법을 제공합니다.
– Streaming API : 성능이 중요할 때 사용.
– Data Binding : 편리한 사용을 원할 때 사용.
– Tree Model : XML처럼 노드형태로 Json 데이터를 다룸. 유연성이 필요할 때 사용.
Streaming API만을 사용한다면 core 라이브러리만으로도 가능하고, Data Binding을 사용한다면 mapper 라이브러리도 필요합니다.
자바 객체와 같은 구조를 갖는 JSON 간에 상호 변환하는 기능을 제공하는 ObjectMapper 클래스를 사용합니다.
– json string -> java object
{ “name”:”홍길동”, “age”:”25″, “favoriteFood”:[“김치볶음밥”, “부대찌개”, “비빔밥”], “etc”:{“email”:”abc@naver.com“, “address”:”xxx”} }
GSON 예제에서 사용한 같은 형태의 json string 입니다. ObjectMapper 객체를 생성 후 readValue() 메서드를 사용하여 자바 객체로 변환합니다.
– java object -> json string
Jackson 은 null 데이터가 있을 경우 문자열로 간주하고 변환을 하는데요. (GSON은 null 데이터 변환하지 않음)
map 객체가 null인 데이터를 json string으로 변환시 아래의 메서드를 사용하여 제외시키기 설정도 가능합니다.
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES); |
두 라이브러리 사용 시 DateTime의 차이점이 있는데,
GSON의 경우 Date 기본 표현으로 Mar 31, 2014 10:54:22 AM 와 같은 형태로 나타나고, Jackson의 경우 Date 기본 표현으로 1396267362196 UTC 기준으로 표현됩니다.
사용하실 때 참고하시면 좋겠습니다. GSON은 GsonBuilder 클래스를 사용하여 원하는 형태로 Date 형태를 변환하실 수 있습니다.
3. GSON vs JACKSON 성능 비교
두 라이브러리에 대해 조사해 보면서 Gson과 Jackson의 성능을 비교하는 글들도 많이 보았는데요.
http://devcafe.nhncorp.com/nts_bp/board_2/1962393 – [공유] Jackson vs Gson
http://devcafe.nhncorp.com/srequest/339076 – JSON <-> Java 변환 라이브러리에 대한 거버넌스 결과
http://blaazinsoftwaretech.blogspot.kr/2013/08/jackson-2-vs-gson-performance-comparison.html?m=1 – Jackson 2 VS GSON Performance Comparison
마지막 주소에 있는 내용입니다.
간단한 객체를 가지고 각각의 JSON 라이브러리를 사용하여 json string 으로 변환하는 테스트 입니다.
아래 그래프의 경우 루프가 반복될 때마다 각각의 JSON 라이브러리의 인스턴스를 생성하였을때의 결과입니다.
Jackson에 비해 GSON의 성능이 월등하게 높아보입니다.
하지만 반대로 객체를 한번만 생성하여 사용하게 될 경우, Jackson이 GSON보다 좋은 성능을 나타내고 있습니다.
ObjectMapper 객체의 생성시간이 250ms 정도 걸리는데, ObjectMapper 의 생성비용을 제외한다면 Jackson이 대체적으로 성능이 우수하다고 합니다.
XML API에서 날짜가 넘어왔는데 String으로 받고 보니까 이렇게 생겼다.
“Thu Jan 19 10:00:00 KST 2012”
내 목적은 2016.01.19 형식으로 변환하는것.
일단 DATE로 변환시키고 2016.01.19 형태로 스트링으로 저장할 것임.
DateFormat dateFormat = new SimpleDateFormat(“EEE MMM dd HH:mm:ss z yyyy”, Locale.ENGLISH);
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy.MM.dd”, Locale.KOREA); String beforeDate = “Thu Jan 19 10:00:00 KST 2016″; Date date = dateFormat.parse(beforeDate); String afterDate = sdf.format(date); |