Java 예외 처리가 꽤 비쌉니다.
프로그램의 시작 부분에 특정 유형의 예외 인스턴스를 작성하고 새 예외를 작성하지 않고 항상 동일한 예외 오브젝트를 던지는 것이 좋은 실행인지 여부를 묻습니다.
나는 단지 예를 들고 싶다. 공통 코드 :
if (!checkSomething(myObject))
throw new CustomException("your object is invalid");
대안 :
static CustomException MYEXP = new CustomException("your object is invalid");
//somewhere else
if (!checkSomething(myObject))
throw MYEXP;
물론, 여기에 몇 가지 가정을하고 있습니다.
MyCustomException
매개 변수가 없다.그래서 질문은 :
나는 이것이 유휴 / 바보 같은 질문이 아니길 바래, 나는 이것에 대해 궁금해. 예외 처리의 실제 비용은손질그리고 창조가 아닙니다.
편집하다FOSDEM 프리젠 테이션에 대한 정확한 토론 추가 참조
면책 조항 : 아무도 내 코드가 제안 된 것과 같이 작동하지 않으며 이와 같은 예외를 관리 할 의도가 없습니다. 단지 "what-if"질문을 수행하고 있습니다.이 호기심은 해당 동영상의 affumation에서 생성됩니다. 나는 이것이 스칼라에서 완성 되었다면 왜 자바가 아닌지 생각했다.
아니, 그러지 마. 비싼 부분은 예외를 처리하지 않고 스택 추적을 생성합니다. 불행히도 stacktrace 또한 유용한 부분입니다. 저장된 예외를 던지면 오해의 소지가있는 스택 추적을 전달하게됩니다.
Scala를 구현하는 과정에서 이것이 가능하다는 상황이있을 수 있습니다. (어쩌면 그들은 재귀 적으로 뭔가를하고 있으며 예외 객체를 미리 생성하기를 원하기 때문에 메모리가 부족할 경우 예외를 생성 할 수 있습니다.) 또한 그들은 그들이하는 일에 대한 많은 정보를 가지고 있기 때문에 더 좋은 기회를 가질 수 있습니다 그것을 올바르게하는 것. 그러나 JVM 언어 구현 자에 의한 최적화는 매우 특별한 경우입니다.
그래서 네가되지 않을거야.파괴오해의 소지가있는 정보를 제공하는 것이 파손을 초래한다고 생각하지 않는 한, 나에게 큰 위험이 될 것 같습니다.
stacktrace를 사용하지 않고 예외를 만드는 방법에 대한 Thomas Eding의 제안을 시도해보십시오.
groovy:000> class MyException extends Exception {
groovy:001> public Throwable fillInStackTrace() {}}
===> true
groovy:000> e = new MyException()
===> MyException
groovy:000> Arrays.asList(e.stackTrace)
===> []
또한 체크 아웃JLS:
NullPointerException (일종의 RuntimeException)은 다음과 같습니다. 메소드에 의해 throw됩니다. blowUp는 main의 try 문에 걸리지 않습니다. NullPointerException이 유형의 변수에 할당 할 수 없기 때문에 망 쳤어. 이렇게하면 finally 절이 실행되고 그 후에 테스트 프로그램의 유일한 스레드 인 메인 실행 쓰레드 catch되지 않는 예외로 인해 종료됩니다. 일반적으로 예외 이름과 간단한 백 트레이스를 인쇄 할 때. 그러나, backtrace는이 사양에서 요구되지 않습니다.
백 트레이스를 위임하는 문제는 예외가 프로그램의 한 지점에서 생성되어 나중에 작성됩니다. 그것은 예외적으로 스택 추적을 저장하는 데 엄청나게 비쌉니다. 실제로 throw됩니다 (이 경우 추적은 스택 풀기). 그러므로 우리는 모든 사람에게 역 추적을 요구하지 않습니다. 예외.
Q1. 이것은 좋은 습관입니까?
내 책에는 없어요. 그것은 복잡성을 추가하고 진단을 방해합니다 (Q2에 대한 나의 답변 참조).
Q2. 이것은 일부 JVM 메커니즘을 손상 시키는가?
이러한 예외 객체에서 의미있는 스택 추적을 얻지는 못합니다.
Q3. 1 인 경우 실적이 향상됩니까? (나는 생각하지 않지만 확실하지는 않다)
Q4. 1과 3이 그렇다면, 왜 연습으로 후원을하지 않습니까?
위에 설명 된 문제로 인해.
Q5. 1이 no이면 Scala에 대한 소개에서 Martin Odersky가 Scala가 어떤 경우에 작동하는 방식이라고 말한 이유는 무엇입니까? (미안하지만, 나는이 순간에이 긍정의 문맥을 기억할 수 없다) Fosdem 2009
문맥없이 대답하기가 어렵습니다.
할 수는 있지만 예외는 있습니다.
초기 스택 추적은 이후 사용시 혼란을 야기하므로 스택 추적이 없어야합니다.
억제 된 예외를 받아들이지 않아야합니다. 복수의 thread가 억제 된 예외를 추가하려고하면 (자), 일이 파탄합니다.
그래서 당신의 예외 생성자가해야합니다.
super(msg, cause, /*enableSuppression*/false, /*writableStackTrace*/false);
유용할까요? 예, 그렇다면 왜이 두 부울 플래그가 첫 번째 위치에 존재합니까?
일부 복잡한 경우에는 예외를 흐름 제어 장치로 사용할 수 있으므로 더 간단하고 빠른 코드가 생성 될 수 있습니다. 이러한 예외를 "예외 제어"라고합니다.
예외가 프로그램에서 예외적으로 잘못된 것을 나타내려면 전통적인 예외를 사용하십시오.
예외는 상대적으로 비싸고 최소한으로 유지해야하지만 비용이 많이 들지 않아 "성능 목적으로"무딘 작업을해야합니다. 너무 조그마한 구실로 조기 최적화가 어떤 희생을 치르더라도 피해야합니다. 이것이 완전히 사실은 아니지만 느린 예외가 얼마나되는지 측정 할 수 있습니다.
long start = System.nanoTime();
int exceptionCount = 0;
for (int i = 0; i < 20000; i++)
try {
int j = i / (i & 1);
} catch (ArithmeticException ae) {
exceptionCount++;
}
long time = System.nanoTime() - start;
System.out.printf("Each exception took average of %,d ns%n", time / exceptionCount);
나는 합리적인 견적이라고 믿는 것을 인쇄합니다.
Each exception took average of 3,064 ns
참고 : 루프 수가 증가하면 Exception이 최적화됩니다. 즉 10 배 반복
Each exception took average of 327 ns
10 배 이상
Each exception took average of 35 ns
10 배 이상
Each exception took average of 5 ns
예외가 충분히 발생하면 JIT는 Exception을 최적화 할만큼 똑똑합니다.
if
필요하다then
어떤 것else
잘못된 것입니다. - NominSim