Java에서 메소드 매개 변수를 final로 선언하는 성능 이유가 있습니까?


117

Java에서 메소드 매개 변수를 final로 선언하는 성능 이유가 있습니까?

에서와 같이 :

public void foo(int bar) { ... }

대:

public void foo(final int bar) { ... }

그것이 bar읽기 전용이고 foo().


메소드 매개 변수를 final로 선언했는지 여부를 컴파일러가 신경 쓰는 이유를 생각할 수 없습니다. 그러나이 질문에 대한 실제 대답은 두 개의 함수를 작성하는 것입니다. 하나는 최종 매개 변수와 다른 하나는 일반 매개 변수입니다. 각각 백만 번 실행하고 눈에 띄는 런타임 차이가 있는지 확인하십시오. 성능이 걱정된다면 코드에 대해 몇 가지 프로파일 링 작업을 수행하고 속도를 늦추는 것이 무엇인지 정확히 알아내는 것이 매우 중요합니다. 그것은 당신이 기대했던 것과 거의 확실히
다릅니다.

1
마이크로 벤치 마크를 작성하지 않는 것이 좋습니다. 당신은 JIT가 할 수있는 최적화 모르는 경우, 당신은 아마 그냥 "간단한 테스트 케이스를"일이 어떻게 동작 하는지를 잘못된 아이디어를 얻을 것이다
Edmondo1984

물론 그 수 있지만, 여기에 아무도 ... 기록되지 또는 마이크로 벤치를 제안했다

1
@ Mike Blandford의 대답은 마이크로 벤치 마크를 사용하는 것이 좋지 않습니까?
Ben Page

자바 마이크로 벤치 마크를 작성하는 것은 뭔가 아주 아주 까다 롭습니다
Edmondo1984

답변:


97

final 키워드는 로컬 변수 및 매개 변수에 대한 클래스 파일에 표시되지 않으므로 런타임 성능에 영향을 미치지 않습니다. 유일한 용도는 변수가 변경되지 않도록 (많은 사람들이 사용에 대한 모호한 이유를 고려하는) 코더 의도를 명확히하고 익명의 내부 클래스를 처리하는 것입니다.

메서드는 수정 자에 관계없이 어쨌든 런타임에 최적화 컴파일러에 의해 인라인되므로 메서드 자체의 최종 수정자가 성능 향상을 가져 오는지에 대한 많은 논쟁이 있습니다. 이 경우 메서드 재정의를 제한하는 데만 사용해야합니다.


5
하지만 최종 변수 / 매개 변수는 루프 변수로 최적화 될 수 있다고 생각할 것입니다.하지만 좋은 컴파일러 / 런타임은 어쨌든 final없이 알아낼 수 있어야합니다 ...
John Gardner

9
두 방법의 유일한 차이점이 지역 변수의 "최종성"일 때 Sun의 컴파일러가 약간 더 짧은 바이트 코드를 방출하는 것을 보았습니다. 마이크로 최적화는 실제이며 컴파일러는 실제로이를 수행합니다. 물론 정말 중요한 것은 JIT가 바이트 코드로 수행하는 작업이며 로컬 참조는 바이트 코드로 컴파일 될 때 "최종성"을 잃습니다. 이것이 최종 지역 변수에 대해 너무 많은 추측이있는 이유라고 생각합니다. 결과가 무엇인지는 매우 비 결정적입니다. 그러나 최종 로컬을 사용하면 바이트 코드에 영향을 미칠 수 있습니다.
Christopher Schultz 2013 년

비 결정적이므로 실제로 최적화에 의존 할 방법이 없습니다. 물론 2008 년 원래 답변 이후 VM 구현에서 많은 부분이 변경되었을 수 있습니다. ;-)
Robin

15

최종 매개 변수의 유일한 이점은 익명 중첩 클래스에서 사용할 수 있다는 것입니다. 매개 변수가 변경되지 않으면 컴파일러는 최종 수정 자 없이도 정상 작동의 일부로 이미이를 감지합니다. 매개 변수가 예기치 않게 할당되어 버그가 발생하는 경우는 매우 드뭅니다. 메소드가이 수준의 엔지니어링이 필요할만큼 충분히 크면 작게 만드십시오. 호출하는 메소드는 매개 변수를 변경할 수 없습니다.


8
"매개 변수가 예기치 않게 할당되어 버그가 발생하는 경우는 매우 드뭅니다." 생각보다 더 흔합니다 ...
RAY

2
@RAY 당신이 옳을 수도 있습니다. 사실 저는 그 주장을 뒷받침 할 데이터 (내 경험을 넘어선)가 없습니다.
Dobes Vandermeer 2012

@DobesVandermeer 더 정확하게 말하자면, 그것은 실제로 "최종 매개 변수 에 대한 이점"이 아닙니다 . 설명하는 것은 익명의 중첩 클래스의 로컬 범위에 표시되는 모든 로컬 변수 (매개 변수 포함)에 대한 필수 구문입니다.
swooby

0

JIT 컴파일러와 같이 클래스로드 후에 작동하는 컴파일러는 최종 메서드를 활용할 수 있습니다. 결과적으로 final로 선언 된 메서드는 성능상의 이점을 가질 수 있습니다.

http://www.javaperformancetuning.com/tips/final.shtml

아 그리고 또 다른 좋은 자원

http://mindprod.com/jgloss/final.html


10
문제는 매개 변수가 최종적으로 선언되어 성능에 영향을 미치지 않는 것에 관한 것이 었습니다.
Robin

최신 JIT 'S (핫스팟) 결승에서는 매개 변수 또는 클래스에 적용되는지 여부에 관계없이 (측정 가능한) 성능 영향이 전혀 없습니다
kohlerm

2
두 기사를 모두 링크하면 final이 개발자에게 의미 론적 표시이며 JIT 컴파일러가 final을 사용할 수 있음을 암시합니다 (다른 사람들이 지적했듯이 실제로 해당 정보가 필요하지 않습니다). 따라서 final은 다소 의미 론적이며, 이는 명시 적으로 const로 표시되지 않은 경우에도 변수 및 메서드의 constness를 추론하는 최신 C / ++ 컴파일러 기능과 병행합니다.
ron

0

메서드 내에서 선언 된 비 최종 지역 변수를 사용하는 것보다 한 가지 더 강조하면 내부 클래스 인스턴스가 스택 프레임보다 오래 지속될 수 있으므로 내부 개체가 아직 살아있는 동안 지역 변수가 사라질 수 있습니다.


-2

컴파일러가 int와 같은 기본 유형을 가진 모든 개인 정적 최종 변수를 제거하고 C ++ 매크로와 마찬가지로 코드에서 직접 인라인 할 수 있다고 가정합니다.

그러나 이것이 실제로 수행되는지 여부는 알 수 없지만 약간의 메모리를 절약하기 위해 수행 할 수 있습니다.


질문은 개인 통계 최종 변수에 관한 것이 아닙니다.
Marquis of Lorne 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.