자바에 인라인 함수가 있습니까?


112

자바에 인라인 함수의 개념이 있습니까? 아니면 다른 것을 대체합니까? 있다면 어떻게 사용합니까? public, staticfinal메서드가 인라인 함수 라고 들었습니다 . 우리 자신의 인라인 함수를 만들 수 있습니까?



3
사소한 의견으로, 조기 최적화는 모든 악의 근원입니다. 공개, 정적 및 최종의 특성을 완전히 이해하지 않으면 인라인이 미칠 수있는 영향을 실제로 이해할 수 없으며 이는 사용중인 JVM에 따라 다릅니다. 인라인이 필요한 이유에 대해 먼저 답하십시오. 다른 곳에서 수행 할 수있는 더 높은 ROI 최적화가 있다는 것이 거의 확실합니다.
Nathaniel Ford

답변:


123

Java에서 최적화는 일반적으로 JVM 수준에서 수행됩니다. 런타임시 JVM은 인라인 할 메서드를 결정하기 위해 "복잡한"분석을 수행합니다. 인라인에서 공격적 일 수 있으며 핫스팟 JVM은 실제로 비 최종 메소드를 인라인 할 수 있습니다.

자바 컴파일러는 거의 모든 메소드 호출을 인라인하지 않습니다 (JVM은 런타임에 모든 것을 수행합니다). 인라인 컴파일 시간 상수 (예 : 최종 정적 기본 값)를 수행합니다. 그러나 방법은 아닙니다.

더 많은 리소스 :

  1. 기사 : Java HotSpot 성능 엔진 : 메소드 인라인 예제

  2. Wiki : Inlining in OpenJDK , 완전히 채워지지는 않았지만 유용한 토론에 대한 링크가 포함되어 있습니다.


15

아니요, Java 에는 인라인 함수 가 없습니다 . 예, 공용 클래스에 배치하면 코드의 어느 위치에서나 공용 정적 메서드를 사용할 수 있습니다. 자바 컴파일러는 정적 또는 최종 메서드에서 인라인 확장 을 수행 할 수 있지만 보장되지는 않습니다.

일반적으로 이러한 코드 최적화는 매우 자주 사용되는 코드 세그먼트에 대해 JVM / JIT / HotSpot과 결합하여 컴파일러에 의해 수행됩니다. 또한 매개 변수의 레지스터 선언과 같은 다른 최적화 개념은 Java에서 알려져 있지 않습니다.

최적화는 Java의 선언에 의해 강제 될 수 없지만 컴파일러와 JIT에 의해 수행됩니다. 다른 많은 언어에서 이러한 선언은 종종 컴파일러 힌트 일뿐입니다 (프로세서보다 더 많은 레지스터 매개 변수를 선언 할 수 있으며 나머지는 무시됩니다).

java 메소드를 static, final 또는 private로 선언하는 것도 컴파일러에 대한 힌트입니다. 당신은 그것을 사용해야하지만 보장은 없습니다. Java 성능은 정적이지 동적입니다. 시스템에 대한 첫 번째 호출은 클래스로드로 인해 항상 느립니다. 다음 호출은 더 빠르지 만 메모리와 런타임에 따라 가장 일반적인 호출은 실행중인 시스템 내에서 최적화되므로 런타임 중에 서버가 더 빨라질 수 있습니다!


3
finalJIT 인라이닝에 영향을주지 않음
Steve Kuo 2013

1
+1,하지만 메소드의 컴파일 된 버전이 인라인되었는지 어떻게 테스트 할 수 있습니까?
Pacerier 2014 년

@Pacerier 그런데 인라인 여부를 테스트해야하는 이유는 무엇입니까?
Arne Burmeister

14

Java는 메소드가 인라인되어야 함을 수동으로 제안하는 방법을 제공하지 않습니다. @notnoop이 주석에서 말했듯이 인라인은 일반적으로 실행 시간에 JVM에서 수행됩니다.


3
대부분의 자바 컴파일러는 메소드 호출을 인라인하지 않습니다. 대부분 JVM이 그렇게합니다.
notnoop

명확히 해주셔서 감사합니다. 정확히 어떤 단계에서 일어 났는지 확신하지 못했습니다. 그것을 반영하기 위해 내 게시물을 편집 할 것입니다.
Thomas Owens

는 않지만, 공공 아니다 @ThomasOwensjdk.internal.vm.annotation.ForceInline
유진

4

위에서 말한 것이 맞습니다. 때로는 최종 메소드가 인라인으로 생성되지만 Java에서 인라인 함수를 명시 적으로 생성하는 다른 방법은 없습니다.


5
최종 메서드는 인라인이 보장되지 않습니다.
Thomas Owens

4
HotSpot에서 추가 final는 메서드가 인라인되었는지 여부에 대한 차이를 만들지 않습니다.
Tom Hawtin-tackline

4
@Thomas는 - 내가 말한 이유 "때때로 마지막 방법 ..."입니다
GreenieMeanie

@ TomHawtin-tackline에 대한 권위있는 출처가 있습니까? 내가 아는 한, 최종 메소드는 타입 가드를 사용하지 않고 인라인 될 수 있습니다. 즉, 수정자가 수정자가없는 것보다 메소드를 더 효율적으로 인라인 할 수 있습니다. Jikes RVM은 인라인 여부를 결정할 때 이것을 고려한다는 것을 알고 있습니다. HotSpot이 비슷한 일을하지 않는다고 확신하십니까?
Jannik Jochem 2015 년

2

실제 사례 :

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

그런 다음 다른 클래스에서 코드가 만료되면 종료 할 수 있습니다. 다른 클래스의 EXPIRED_ON 변수를 참조하면 상수가 바이트 코드에 인라인되어 만료 날짜를 확인하는 코드의 모든 위치를 추적하기가 매우 어렵습니다. 그러나 다른 클래스가 isExpired () 메서드를 호출하면 실제 메서드가 호출됩니다. 즉, 해커가 isExpired 메서드를 항상 false를 반환하는 다른 메서드로 바꿀 수 있습니다.

컴파일러가 정적 최종 메서드를 참조하는 모든 클래스에 인라인하도록 강제하는 것이 매우 좋을 것이라는 데 동의합니다. 이 경우 런타임에 필요하지 않으므로 Control 클래스를 포함 할 필요도 없습니다.

내 연구에서 이것은 할 수 없습니다. 아마도 일부 Obfuscator 도구가이를 수행 할 수 있거나 컴파일 전에 소스를 편집하도록 빌드 프로세스를 수정할 수 있습니다.

컨트롤 클래스의 메서드가 컴파일 중에 다른 클래스에 인라인으로 배치되었는지 확인하려면 클래스 경로에서 Control 클래스없이 다른 클래스를 실행 해보십시오.


2

자바에서 "인라인"메소드라고 할 수있는 메소드가 있지만 jvm에 따라 다릅니다. 컴파일 후 메소드의 기계 코드가 35 바이트 미만이면 즉시 인라인 메소드로 전송되며, 메소드의 기계어 코드가 325 바이트 미만이면 jvm에 따라 인라인 메소드로 전송 될 수 있습니다.


1
이들은 기본적으로 오라클의 VM에 대한 값은 참조 docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

따라서 존재하지 않는 것 같지만 구아바 또는 동등한 Function 클래스 구현을 사용하여이 해결 방법을 사용할 수 있습니다. 해당 클래스는 매우 간단합니다. 예 :

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

예, 이것은 복잡한 코드 블록 ({} 내에서)을 생성하는 방법을 예시하기위한 데드 코드입니다. AKA 인라인이라는 메서드를 생성하는 데 방해가되지 않는 특정 작업을 수행합니다!


합리적인 아이디어 인 것 같습니다. Google 공용 라이브러리를 사용하지 않는 버전이 있습니까?
ragerdl

0

Java9에는 인라인으로 볼 수있는 런타임이 아닌 컴파일 타임에 여러 최적화를 수행하는 "Ahead of time"컴파일러가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.