저번 글에서 아래 두개의 코드는 같은 일을 수행한다고 글을 쓴 적이 있었다.
즉, 이 둘을 보면 컴파일러는 람다식을 익명객체로 변환한다고 볼 수 있다고 생각할 수도 있다. 이 둘을 컴파일하고 javap로 디컴파일 하여 과연 바이트코드가 같은 지 확인해보겠다.
결론부터 말하면 익명객체와 람다식은 서로 다르다.
바이트코드를 얼핏 봐도 위에는 INVOKESPECIAL 이라는 JVM 명령어를 쓰고 있고, 아래는 INVOKEDYNAMIC이라는 JVM 명령어를 사용함을 볼 수 있다. 이 둘의 차이점이 뭔지 간단하게(깊지 않게) 고민해봤다.
익명 클래스
바이트 코드
1. Ex14_0의 내부 클래스인 INNERCLASS가 만들어지고 Ex14_0$1의 클래스가 새롭게 생성되었음을 위의 바이트 코드와 다음 클래스에서 확인할 수가 있다.
2. INVOKESPECIAL은 생성자 초기화메서드, Super 메서드 호출을 위한 JVM 명령어 이다. 즉, 익명클래스를 초기화 했음을 알 수가 있다.
람다
바이트코드
위 익명 클래스와 다르게 클래스를 별도로 생성하는 코드가 없다. 단, INVOKEDYNAMIC이라는 JVM 명령어를 볼 수가 있는 데, 이는 JDK 1.7부터 새롭게 생긴 JVM 명령어 이다.
INVOKEDYNAMIC은 Indy 라고도 한다.
JDK 1.7 이전에는 JVM 명령어에는 총 4가지가 있었다. invokeinterface, invokevirtual, invokestatic, invokespecial.
각각의 명령어들은 메서드를 호출하기 위해 컴파일단계에서 호출하는 명령어. 런타임단계에서 호출하는 명령어들이다.
런타임 접근 방식은 invokeinterface라 볼 수가 있는데, 이 호출 방식은 리플렉션 기반이므로 결과적으로 비효율적이다. 반면 컴파일 타임 솔루션은 컴파일 타임에 코드 생성에 의존하기 때문에 처리해야 할 바이트 코드가 많아져 시작 시간이 느려질 수가 있다.
그래서 생긴 invokedynamic 즉, Indy를 사용하면 원하는 방식으로 메서드 invoke process를 부트스트랩 할 수 있다. 다시 말해서 JVM이 호출된 동적 연산자를 처음 발견하면 리플렉션을 사용하는 것이 아닌 부트스트랩 메서드라고 하는 특수 메서드(LamdaMetafactory)를 호출하여 invoke process를 초기화 한다. 그냥 이 명령어들을 사용하면서 성능이 향상됐다고 생각하면 될 것같다.
더 궁금하면 다음 사이트에 가서 공부하면 된다.
https://www.baeldung.com/java-invoke-dynamic
JVM 명령어들
- invokeinterface : 인터페이스 메서드를 호출하는 데 사용되며 런타임에 이 인터페이스 메서드를 구현하는 객체를 검색하고 호출할 적절한 메서드를 찾는다.
- invokevirtual : 이 명령어는 객체의 인스턴스 메서드를 호출하고 객체의 실제 유형에 따라 디스패치하는 데 사용
- invokestatic : 클래스 메서드를 호출하는 데 사용(클래스(정적) 메서드 호출)
- invokespecial : 인스턴스 초기화 메서드, 부모 클래스 메서드 등 특별한 처리가 필요한 일부 인스턴스 메서드를 호출하는 데 사용(참고로 private메서드는 이제 invokevirtual 명령어로 호출된다)
- invokedynamic : JDK 1.7에서 새로운 가상머신 명령어가 추가됐다. 동적 메서드를 호출할 때 사용. 람다식도 이에 포함된다.
예시)
레퍼런스
- https://devfunny.tistory.com/912
- https://blog.csdn.net/kangkanglou/article/details/79422520
- https://www.baeldung.com/java-invoke-dynamic
- https://sujl95.tistory.com/76
'공부방 > JAVA' 카테고리의 다른 글
Map의 EntrySet()에 대한 자세한 설명(맵을 탐색하는 4가지 방법) (0) | 2023.12.10 |
---|---|
람다식 기본 - 백기선 자바라이브스터디 (2) | 2023.12.02 |
코드 품질 향상을 위한 제네릭(Generic) - 백기선 자바라이브스터디 (1) | 2023.10.30 |
@GetterSetter을 만들어보자 (0) | 2023.10.12 |
I/O - 백기선 자바라이브스터디 (2) | 2023.10.10 |