자바에 인라인 함수의 개념이 있습니까? 아니면 다른 것을 대체합니까? 있다면 어떻게 사용합니까? public
, static
및 final
메서드가 인라인 함수 라고 들었습니다 . 우리 자신의 인라인 함수를 만들 수 있습니까?
자바에 인라인 함수의 개념이 있습니까? 아니면 다른 것을 대체합니까? 있다면 어떻게 사용합니까? public
, static
및 final
메서드가 인라인 함수 라고 들었습니다 . 우리 자신의 인라인 함수를 만들 수 있습니까?
답변:
Java에서 최적화는 일반적으로 JVM 수준에서 수행됩니다. 런타임시 JVM은 인라인 할 메서드를 결정하기 위해 "복잡한"분석을 수행합니다. 인라인에서 공격적 일 수 있으며 핫스팟 JVM은 실제로 비 최종 메소드를 인라인 할 수 있습니다.
자바 컴파일러는 거의 모든 메소드 호출을 인라인하지 않습니다 (JVM은 런타임에 모든 것을 수행합니다). 인라인 컴파일 시간 상수 (예 : 최종 정적 기본 값)를 수행합니다. 그러나 방법은 아닙니다.
더 많은 리소스 :
Wiki : Inlining in OpenJDK , 완전히 채워지지는 않았지만 유용한 토론에 대한 링크가 포함되어 있습니다.
아니요, Java 에는 인라인 함수 가 없습니다 . 예, 공용 클래스에 배치하면 코드의 어느 위치에서나 공용 정적 메서드를 사용할 수 있습니다. 자바 컴파일러는 정적 또는 최종 메서드에서 인라인 확장 을 수행 할 수 있지만 보장되지는 않습니다.
일반적으로 이러한 코드 최적화는 매우 자주 사용되는 코드 세그먼트에 대해 JVM / JIT / HotSpot과 결합하여 컴파일러에 의해 수행됩니다. 또한 매개 변수의 레지스터 선언과 같은 다른 최적화 개념은 Java에서 알려져 있지 않습니다.
최적화는 Java의 선언에 의해 강제 될 수 없지만 컴파일러와 JIT에 의해 수행됩니다. 다른 많은 언어에서 이러한 선언은 종종 컴파일러 힌트 일뿐입니다 (프로세서보다 더 많은 레지스터 매개 변수를 선언 할 수 있으며 나머지는 무시됩니다).
java 메소드를 static, final 또는 private로 선언하는 것도 컴파일러에 대한 힌트입니다. 당신은 그것을 사용해야하지만 보장은 없습니다. Java 성능은 정적이지 동적입니다. 시스템에 대한 첫 번째 호출은 클래스로드로 인해 항상 느립니다. 다음 호출은 더 빠르지 만 메모리와 런타임에 따라 가장 일반적인 호출은 실행중인 시스템 내에서 최적화되므로 런타임 중에 서버가 더 빨라질 수 있습니다!
final
JIT 인라이닝에 영향을주지 않음
Java는 메소드가 인라인되어야 함을 수동으로 제안하는 방법을 제공하지 않습니다. @notnoop이 주석에서 말했듯이 인라인은 일반적으로 실행 시간에 JVM에서 수행됩니다.
jdk.internal.vm.annotation.ForceInline
위에서 말한 것이 맞습니다. 때로는 최종 메소드가 인라인으로 생성되지만 Java에서 인라인 함수를 명시 적으로 생성하는 다른 방법은 없습니다.
final
는 메서드가 인라인되었는지 여부에 대한 차이를 만들지 않습니다.
실제 사례 :
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 클래스없이 다른 클래스를 실행 해보십시오.
자바에서 "인라인"메소드라고 할 수있는 메소드가 있지만 jvm에 따라 다릅니다. 컴파일 후 메소드의 기계 코드가 35 바이트 미만이면 즉시 인라인 메소드로 전송되며, 메소드의 기계어 코드가 325 바이트 미만이면 jvm에 따라 인라인 메소드로 전송 될 수 있습니다.
따라서 존재하지 않는 것 같지만 구아바 또는 동등한 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 인라인이라는 메서드를 생성하는 데 방해가되지 않는 특정 작업을 수행합니다!