Java Exception 원인 정리 Java 2016. 11. 22. 09:47


Java Exception 원인 정리



ClassNotFoundException클래스를 찾지 못함
CloneNotSupportedExceptionCloneable 인터페이스 미구현
IllegalAccessException클래스 접근을 못함
InstantiationException추상 클래스 또는 인터페이스를 인스턴스화 하고자 할때
InterruptedException쓰레드가 중단 되었을때
NoSuchFieldException지정된 필드가 없을때
NoSuchMethodException지정된 메소드가 없을때
[IOException] CharConversionException문자 변환에서 예외가 발생했을때
[IOException] EOFException파일의 끝에 도달했을때
[IOException] FileNotFoundException파일이 발견되지 않았을때
[IOException] InterruptedIOException입출력 처리가 중단 되었을때
[IOException][ObjectStreamException] InvalidClassException시리얼라이즈 처리에 관한 문제가 클래스 안에 있을때
[IOException][ObjectStreamException] InvalidObjectException시리얼라이즈된 오브젝트에서 입력 검증에 실패했을때
[IOException][ObjectStreamException] NotActiveException스트림 환경이 액티브하지 않을 때 메소드를 호출했을때
[IOException][ObjectStreamException] NotSerializableException오브젝트를 시리얼라이즈 할 수 없을때
[IOException][ObjectStreamException] OptionalDataException오브젝트를 읽을때 기대 이외의 데이터와 만났을때
[IOException][ObjectStreamException] StreamCorruptedException읽은 데이터 스트림이 파손되어 있을때
[IOException][ObjectStreamException] WriteAbortedException기록중에 예외가 발생한 스트림을 읽었을때
[IOException] SyncFailedException시스템 버퍼를 동기시키는 FileDescriptor.sync()의 호출 실패시
[IOException] UnsupportedEncodingException지정된 문자 부호화 형식을 지원하고 있지 않을때
[IOException] UTFDataFormatException부정한 UTF-8방식 문자열과 만났을때
[RuntimeException] ArithmeticException제로제산 등의 산술 예외 발생시
[RuntimeException] ArrayStoreException배열에 부정한 형태의 오브젝트를 저장하고자 할때
[RuntimeException] [IllegalArgumentException] IllegalThreadStateException쓰레드가 요구된 처리를 하기에 적합한 상태에 있지 않을때
[RuntimeException] [IllegalArgumentException] NumberFormatException부적절한 문자열을 수치로 변환하고자 할때
[RuntimeException] IllegalMonitorStateException모니터 상태가 부정일때
[RuntimeException] IllegalStateException메소드가 요구된 처리를 하기에 적합한 상태에 있지 않을때
[RuntimeException] [IndexOutOfBoundException] ArrayIndexOutOfBoundsException범위 밖의 배열 첨자 지정시
[RuntimeException] [IndexOutOfBoundException] StringIndexOutOfBoundsException범위 밖의 String 첨자 지정시
[RuntimeException] NegativeArraySizeException음의 크기로 배열 크기를 지정하였을때
[RuntimeException] NullPointerExceptionnull 오브젝트로 접근했을때
[RuntimeException] SecurityException보안 위반시
[RuntimeException] UnsupportedOperationException지원되지 않는 메소드를 호출했을때
@ Error
[LinkageError] ClassCircularityError클래스 초기화중에 순환 참조를 검출시
[LinkageError] [ClassFormatError] UnsupportedClassVersionErrorJVM이 지원되지 않는 버전의 번호를 가진 클래스 파일을 읽고자 할때
[LinkageError] ExceptionInInitializerError정적 이니셜라이저로 예외가 발생시
[LinkageError] [IncompatibleClassChangeError] AbstracMethodError추상 메소드를 호출했을때
[LinkageError] [IncompatibleClassChangeError] IllegalAccessError접근할 수 없는 메소드와 필드를 사용하고자 했을때
[LinkageError] [IncompatibleClassChangeError] InstantiationError인터페이스 또는 추상 클래스를 인스턴스화하고자 했을때
[LinkageError] [IncompatibleClassChangeError] NoSuchFieldError지정한 필드가 존재하지 않을때
[LinkageError] [IncompatibleClassChangeError] NoSuchMethodError지정한 메소드가 존재하지 않을때
[LinkageError] NoClassDefFoundError클래스 정의가 발견되지 않았을때
[LinkageError] UnsatisfieldLinkError클래스에 포함되는 링크 정보를 해결할 수 없을때
[LinkageError] VerifyError클래스 파일안에 부적절한 부분이 있을때
ThreadDeath쓰레드가 정지해야만 한다는 의미
[VirtualMachineError] InternalError내부에러
[VirtualMachineError] OutOfMemoryError메모리부족으로 메모리를 확보 못함
[VirtualMachineError] StackOverflowError스택 오버 발생
[VirtualMachineError] UnknownError심각한 예외발생


- 출처 : http://kinjsp.pe.kr/lecture/exception.kin -

지난 포스트를 통해 자바로 파일을 복사하는 몇가지 방법을 알아보았다.
이번시간에는 각 코드의 성능을 간단히 확인해 보고자 한다. 


/*
 * author 신윤섭
 */

package filecopy;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;


/**
 * Stream을 이용한 파일복사 코드 스니핏
 * @author 신윤섭
 */

public class StreamCopy {


 /**
  * source에서 target으로의 파일 복사
  * @param source
  * @param target
  */

 
public void copy(String source, String target) {
 
//복사 대상이 되는 파일 생성
 
File sourceFile = new File( source );
 
 
//스트림 선언
 
FileInputStream inputStream = null;
 
FileOutputStream outputStream = null;
 
 
try {
   
//스트림 생성
   inputStream
= new FileInputStream(sourceFile);
   outputStream
= new FileOutputStream(target);
   
   
int bytesRead = 0;
   
//인풋스트림을 아웃픗스트림에 쓰기
   
byte[] buffer = new byte[1024];  
   
while ((bytesRead = inputStream.read(buffer, 0, 1024)) != -1) {
    outputStream
.write(buffer, 0, bytesRead);
   
}
   
 
} catch (Exception e) {
   e
.printStackTrace();
 
}finally{
   
//자원 해제
   
try{
    outputStream
.close();
   
}catch(IOException ioe){}
   
try{
    inputStream
.close();
   
}catch(IOException ioe){}
 
}


 }
}



/*
 * author 신윤섭
 */

package filecopy;


import java.io.File;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;


/**
 * Buffer를 이용한 파일복사 코드 스니핏
 * @author 신윤섭
 */

public class BufferCopy {


 /**
  * source에서 target으로의 파일 복사
  * @param source
  * @param target
  */

 
public void copy(String source, String target) {
 
//복사 대상이 되는 파일 생성
 
File sourceFile = new File( source );
 
 
//스트림, 버퍼 선언
 
FileInputStream inputStream = null;
 
FileOutputStream outputStream = null;
 
BufferedInputStream bin = null;
 
BufferedOutputStream bout = null;
 
 
try {
   
//스트림 생성
   inputStream
= new FileInputStream(sourceFile);
   outputStream
= new FileOutputStream(target);
   
//버퍼 생성
   bin
= new BufferedInputStream(inputStream);
   bout
= new BufferedOutputStream(outputStream);
   
   
//버퍼를 통한 스트림 쓰기
   
int bytesRead = 0;
   
byte[] buffer = new byte[1024];
   
while ((bytesRead = bin.read(buffer, 0, 1024)) != -1) {
    bout
.write(buffer, 0, bytesRead);
   
}


  } catch (Exception e) {
   e
.printStackTrace();
 
} finally {
   
//자원 해제
   
try{
    outputStream
.close();
   
}catch(IOException ioe){}
   
try{
    inputStream
.close();
   
}catch(IOException ioe){}
   
try{
    bin
.close();
   
}catch(IOException ioe){}
   
try{
    bout
.close();
   
}catch(IOException ioe){}
 
}
 
}
}



/*
 * author 신윤섭
 */

package filecopy;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.io.IOException;


/**
 * NIO Channel을 이용한 파일복사 코드 스니핏
 * @author 신윤섭
 */

public class ChannelCopy {


 /**
  * source에서 target으로의 파일 복사
  * @param source 복사할 파일명을 포함한 절대 경로
  * @param target 복사될 파일명을 포함한 절대경로
  */

 
public void copy(String source, String target) {
 
//복사 대상이 되는 파일 생성
 
File sourceFile = new File( source );


  //스트림, 채널 선언
 
FileInputStream inputStream = null;
 
FileOutputStream outputStream = null;
 
FileChannel fcin = null;
 
FileChannel fcout = null;


  try {
   
//스트림 생성
   inputStream
= new FileInputStream(sourceFile);
   outputStream
= new FileOutputStream(target);
   
//채널 생성
   fcin
= inputStream.getChannel();
   fcout
= outputStream.getChannel();
   
   
//채널을 통한 스트림 전송
   
long size = fcin.size();
   fcin
.transferTo(0, size, fcout);


  } catch (Exception e) {
   e
.printStackTrace();
 
} finally {
   
//자원 해제
   
try{
    fcout
.close();
   
}catch(IOException ioe){}
   
try{
    fcin
.close();
   
}catch(IOException ioe){}
   
try{
    outputStream
.close();
   
}catch(IOException ioe){}
   
try{
    inputStream
.close();
   
}catch(IOException ioe){}
 
}
 
}
}



이상의 샘플코드를 이용하여 700Mbytes 짜리 파일을 5번 복사하여 그 시간을 측정해 본 결과는 아래와 같다.
테스트는 Win XP Pro sp3, Intel Core2 Duo 2GHz, 2Gbytes, 5400rpm의 노트북용 HDD 에서 JDK 1.6.0_06
을 이용하여 이루어졌다.

결과는 아래와 같다.

스트림을 이용한 파일 카피

Stream을 이용한 파일 복사


버퍼를 이용한 파일 카피

Buffer를 이용한 파일 복사


채널을 이용한 파일 카피

Channel을 이용한 파일 복사



프로파일러를 이용하여 측정한 값이기 때문에 프로파일러의 처리량 만큼의 차이는 있겠지만 상대적 성능 비교
에는 문제가 없으리라 생각 된다. 
실측에서도 예상대로 Stream , Buffer, Channel 순으로 파일 복사 시간이 줄어들고 있음을 볼 수있다.

이번에는 조금 더 들여다 보기로 하자. 700m짜리 파일을 한번 복사하는데 어떤 클래스와 메소들이 참여하고 
있는지, 그리고 메소드가 몇번이나 호출되고 있는지 확인 해 보는것도 재미있을 것이다.

스트림이용

FileInputStream.read()실행에 대부분의 시간을 소비하고 있다.


스트림을 이용한 파일복사이다. FileInputStream.read()메소드가 71만여번 호출되고있으며 실행시간의 대부분을 
이 메소드를 실행 하는데 소비하고 있음을 알 수 있다.

버퍼이용

Stream보다는 나아졌다고는 하나 역시 read()메소드가 대부분의 실행시간을 소비하고 있다.


Buffer를 이용한 방법. 위의 Stream을 이용한 방법에 비해 수행시간이 약간은 줄어들었지만 이는 Buffer를 활용
함으로써 FileOutputStream.write() 수행시간을 줄인데 따른 성능 향상이며, FileInputStream.read()메소드는
약 9만번 호출되고 있다.

채널이용

위 두 방식과는 확연히 다른 동작 성향을 보여주고 있다.


마지막으로 채널을 이용한 파일복사의 경우 위 두 경우와 비교하여 호출되는 메소드나 호출횟수등 전혀 다른 
동작 성향을 보이고 있다. read 도 하지 않은채 FileDispatcher.write() 메소드를 단 한번 호출 하는것으로 파일
복사를 끝내고 있다. 이 FileDispatcher.write() 하부구조에서는 OS의 네이티브IO를 호출하고 있으리라 미루어
짐작할 수 있다.

이상으로 파일복사(스트림전송)의 세가지 방식과 그 성능에 대해 간략하게 알아보았다.
위 실험 결과는 크기가 비교적 큰 파일의 복사에서 나타나는 성향며, 다수의 작은 크기의 파일을 복사한다면
그 결과가 달라질 수도 있음을 밝혀둔다.

io작업이 필요한데 JDK 1.4 이상의 버전을 이용할 수 있다면 나은 성능을 보장하는 nio를 사용하지
않을 이유가 없어보인다.


출처 : http://www.yunsobi.com/blog/406

자바로 파일을 복사할 수 있는 방법은 크게 3가지 정도가 있다.
InputStream, OutputStream을 이용한 방법, Buffer를 이용한 방법, Channel을 이용한 방법이 그것이다.
물론 Buffer를 이용하면서도 단순히 Stream에 Buffer 필터를 적용할 수도, MappedByteBuffer를 쓸 수도 있고
Channel을 이용하면서도 inputChannel과 outputChannel을 이용하거나 transterTo()를 이용하는 등
다양한 방법을 구사할 수 있다.
여기서는 자바로 구현 할 수 있는 대표적인 파일 복사 코드를 살펴보고 각 코드간의 성능에 대한 이야기도 나눠
보도록 하겠다.

Java입문서등을 통하여 io (Input/Output)부분을 언급하며 나오는 개념이 Stream일 것이다. 스트림의 개념을
설명하고 처음 접하는 코드는 아래와 유사할 것이다. 파일을 인풋스트림으로 읽어들인 후 그 길이만큼 아웃풋
스트림에다 흘려보내는 방식으로 파일을 복사할 수 있다.


FileInputStream inputStream = new FileInputStream(file);
FileOutputStream outputStream = new FileOutputStream(saveFullPath);


int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = inputStream.read(buffer, 0, 1024)) != -1) {
    outputStream
.write(buffer, 0, bytesRead);
}


outputStream.close();
inputStream
.close();


* InputStream과 OutputStream을 이용한 기본적인 파일 복사 코드.
위 코드는 기본적인 Stream의 사용법을 잘 보여주고 있지만 성능상에 심각한 문제를 안고 있다.
파일크기(정확하게는 스트림의 길이)만큼 while문을 돌면서 끊임없이 읽고쓰기를 반복하고 있는데
이는 CPU, DISK모두에게 부담을 주는 결과를 초래한다.

이어지는 코드가 아마 가장 널리쓰이고 흔하게 볼수 있는 코드 일 것이다. 위에서 살펴본 Stream간의 데이터
전송이 썩 좋은 성능을 내지 못하기 때문에, 스트림을 버퍼를 장착(wrapping, chainning)하여 입출력 횟수를 줄여
성능 향상을 꾀하고 있다.


FileInputStream inputStream = new FileInputStream(file);
FileOutputStream outputStream = new FileOutputStream(saveFullPath);

BufferedInputStream bin = new BufferedInputStream(inputStream);
BufferedOutputStream bout = new BufferedOutputStream(outputStream);


int bytesRead = 0;
byte[] buffer = new byte[1024];


while ((bytesRead = bin.read(buffer, 0, 1024)) != -1) {
    bout
.write(buffer, 0, bytesRead);
}


bout.close();
bin
.close();
outputStream
.close();
inputStream
.close();


* Stream에 Buffer Filter를 연결하여 성능을 향상.
위와같은 방법으로 충분히 만족할만 한가? 그렇다고 할수도있고 아니라고 할수도 있다. 위 두 방식은 스트림으로
데이터를 전송하는데 항상 cpu의 연산을 필요로 한다. 즉 스트림을 처리하는동안 cpu가 계속해서 명령을 처리
해줘야 한다는것이다.(비록 cpu사용율은 얼마 안될지 모르지만.. )

컴퓨터의 입장에서 본다면 IO는 상당히 느린 작업중의 하나이다. 이런 작업을 조금이라도 빨리 처리하기위해
하드웨어 혹은 운영체제 수준에서 많은 기법들을 제공하고 있다.
자바는 버전 1.4에 이르러서 기존 io와는 차별화된 nio(new io) 패키지가 추가되었는데 이 nio를 통하여 
운영체제가 제공해 주는 향상된 io기능을 활용할 수 있게 되었다. 그 대표적인 것이 Channel과 Selector일 것이다.
아래와 같은 코드는 JDK 1.4이상부터 사용 가능하며 transferTo() 메소드를 호출하면 내부적으로 OS의 네이티브IO
기능을 활용하여 더욱 효율적인 스트림 전송이 가능하다.
 

FileInputStream inputStream = new FileInputStream(file);        
FileOutputStream outputStream = new FileOutputStream(saveFullPath);


FileChannel fcin =  inputStream.getChannel();
FileChannel fcout = outputStream.getChannel();


long size = fcin.size();
   
fcin
.transferTo(0, size, fcout);


fcout.close();
fcin
.close();
outputStream
.close();
inputStream
.close();


* Channel을 이용한 네이티브OS 기능 사용하기.

이상으로 3가지 대표적인 자바 파일복사 코드를 살펴보았다. 다음 포스트에서는 각 방식의 성능 차이에 대해 
알아보도록 하겠다.


출처 : http://www.yunsobi.com/blog/399