오류 및 오류 처리는 API 클래스를 나타냅니다. 오류 처리와 관련된 오류는 매우 흔하므로 따로 다룰 만한 내용입니다. "API 오용"과 마찬가지로 오류 관련 보안 취약성을 일으키는 두 가지 원인이 있습니다. 가장 흔한 것은 오류를 제대로(혹은 아예) 처리하지 못하는 것입니다. 두 번째는 (잠재적 공격자에게) 너무 많은 정보를 제공하거나 처리하기 어려운 오류를 발생시키는 것입니다.
NullPointerException
을 캐치(catch)하는 것은 일반적으로 잘못된 관행입니다.NullPointerException
을 캐치(catch)합니다. NullPointerException
을 발생시켜 오류 조건을 알립니다.NullPointerException
을 캐치(catch)하는 오류를 범합니다.
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
NullReferenceException
을 캐치(catch)하는 것은 일반적으로 잘못된 관행입니다.NullReferenceException
을 캐치(catch)합니다. NullReferenceException
을 발생시켜 오류 조건을 알립니다.NullReferenceException
을 잘못 catch합니다.
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
finally
블록 내부에서 반환하면 예외 사항이 손실될 수 있습니다.finally
블록에 return 문이 있으면 try 블록에서 발생하는 예외 사항이 사라질 수 있습니다.true
와 함께 두 번째 doMagic
호출에서 발생한 MagicException
은 호출자에게 전달되지 않습니다. finally
블록에 return 문이 있으면 예외 사항이 사라집니다.
public class MagicTrick {
public static class MagicException extends Exception { }
public static void main(String[] args) {
System.out.println("Watch as this magical code makes an " +
"exception disappear before your very eyes!");
System.out.println("First, the kind of exception handling " +
"you're used to:");
try {
doMagic(false);
} catch (MagicException e) {
// An exception will be caught here
e.printStackTrace();
}
System.out.println("Now, the magic:");
try {
doMagic(true);
} catch (MagicException e) {
// No exception caught here, the finally block ate it
e.printStackTrace();
}
System.out.println("tada!");
}
public static void doMagic(boolean returnFromFinally)
throws MagicException {
try {
throw new MagicException();
}
finally {
if (returnFromFinally) {
return;
}
}
}
}
finally
블록 내부에서 반환하면 예외 사항이 손실될 수 있습니다.finally
블록에 return 문이 있으면 try 블록에서 발생하는 예외 사항이 사라질 수 있습니다.True
와 함께 두 번째 doMagic
호출에서 발생한 exception
은 호출자에게 전달되지 않습니다. finally
블록에 return 문이 있으면 예외 사항이 사라집니다."disappear before your very eyes!" . PHP_EOL;
echo "First, the kind of exception handling " .
"you're used to:" . PHP_EOL;
try {
doMagic(False);
} catch (exception $e) {
// An exception will be caught here
echo $e->getMessage();
}
echo "Now, the magic:" . PHP_EOL;
try {
doMagic(True);
} catch (exception $e) {
// No exception caught here, the finally block ate it
echo $e->getMessage();
}
echo "Tada!" . PHP_EOL;
function doMagic($returnFromFinally) {
try {
throw new Exception("Magic Exception" . PHP_EOL);
}
finally {
if ($returnFromFinally) {
return;
}
}
}
?>
ThreadDeath
오류가 다시 발생하지 않는 경우, 문제의 스레드는 실제로 정지된 것이 아닐 수도 있습니다.ThreadDeath
오류는 응용 프로그램을 비동기적으로 종료한 후 정리해야 할 경우에만 발생되어야 합니다. ThreadDeath
오류가 발생한 경우, 스레드가 실제로 정지하도록 다시 발생시키는 것이 중요합니다. ThreadDeath
발생의 목적은 스레드를 중단시키는 것입니다. ThreadDeath
를 덮어버리면 스레드 중단을 막을 수 있고 원래 ThreadDeath
를 발생시킨 사람은 누구라도 스레드 중단을 기대하므로 예기치 못한 동작이 발생할 수 있습니다.ThreadDeath
오류를 찾지만 다시 발생시키지 않습니다.
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
finally
블록 내에서 throw
문을 사용하면 try-catch-finally
를 통한 논리 진행이 깨집니다.finally
블록은 항상 해당 try-catch
블록 뒤에서 실행되며 대개 파일 핸들 또는 데이터베이스 커서와 같이 할당된 리소스를 해제하는 데 사용됩니다. finally
블록에서 예외를 발생시키면 정상적인 프로그램 실행이 손상되므로 중요한 정리 코드를 무시할 수 있습니다. stmt.close()
에 대한 호출은 FileNotFoundException
이 발생할 때 무시됩니다.
public void processTransaction(Connection conn) throws FileNotFoundException
{
FileInputStream fis = null;
Statement stmt = null;
try
{
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
}
catch (FileNotFoundException fe)
{
log("File not found.");
}
catch (SQLException se)
{
//handle error
}
finally
{
if (fis == null)
{
throw new FileNotFoundException();
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
log(e);
}
}
}
}
javax.net.ssl.SSLHandshakeException
, javax.net.ssl.SSLKeyException
및 javax.net.ssl.SSLPeerUnverifiedException
모두 SSL 연결과 관련된 중요한 오류를 전달합니다. 이러한 오류가 올바로 처리되지 않는 경우, 이 연결은 예상치 못한 상태 및 잠재적 불안정 상태가 될 수 있습니다.