본문 바로가기
에러들

Platform declaration clash: The following declarations have the same JVM signature 에러

by Glion 2023. 9. 5.
반응형

Kotlin의 범위함수 apply에 대해 공부하면서 예제코드를 작성할 때였다.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    applyFunction()
}

inner class Person(){
    var name: String?= null
    var age: Int? = null

    fun getName(): String?{
        return name
    }
}

private fun applyFunction(){
    val person = Person().apply{
        name = "ApplyTest"
        age = 1
    }.getName()
    Log.d("Glion", person?: "Null")
}

 

applyFunction() 호출 시 범위함수 apply를 사용하여 person 객체의 속성을 변경하고, getName을 호출하여 person 변수에 name이 저장되게끔 하였다. 그리고 로그를 찍어 확인해보려고 했으나

Platform declaration clash: The following declarations have the same JVM signature
fun `<get-name>`(): String? defined in com.example.oddmentsproject.activity.MainActivity.Person
fun getName(): String? defined in com.example.oddmentsproject.activity.MainActivity.Person

와 같은 오류가 나타났다.

 

구글링을 해보니, 

<get-name>() 과 getName이 같은 JVM signature를 가지고 있다는 것이다.

코틀린코드가 컴파일 될때 자바 바이트코드로 변경되는데 이때 이 JVM signature가 동일하기 때문에 오류가 난다고 한다.

 

내가 짠 코드에서 getName 함수는 하나뿐인데 이게 무슨소리지??

 

같은 JVM signature를 가지고 있다고 하는데, 무슨말인지 모르겠고 로그를 보면 Person 클래스에 getName() 과

'<get-name>' 이 중복되었다고 하고, 바이트 코드로 변경될때 동일한게 있어 오류가 난다고 했으니 위 코드를 자바 바이트 코드로 디컴파일해서 살펴보자.

 

   private final void applyFunction() {
      Person var2 = new Person();
      int var4 = false;
      var2.setName("ApplyTest");
      var2.setAge(1);
      String person = var2.getName();
      String var10001 = person;
      if (person == null) {
         var10001 = "Null";
      }

      Log.d("Glion", var10001);
   }
   
      public final class Person {
      @Nullable
      private String name;
      @Nullable
      private Integer age;

      @Nullable
      public final String getName() { // 이부분과
         return this.name;
      }

      public final void setName(@Nullable String var1) {
         this.name = var1;
      }

      @Nullable
      public final Integer getAge() {
         return this.age;
      }

      public final void setAge(@Nullable Integer var1) {
         this.age = var1;
      }

      @Nullable
      public final String getName() { // 이부분이 동일하다
         return this.name;
      }
   }

이 코드는 위의 Person 클래스 생성부분과 applyFunction() 함수 부분을 디컴파일 한 코드이다.

 

Person 클래스 생성부분을 보면, 멤버변수 name과 age가 private으로 선언되어 있고, 이를 접근하기 위한 getter, setter 가 생성되어 있고, 동일한 getName() 메소드가 정의되어있는걸 확인 할 수 있다.

 

즉, 동일한 함수가 2개 생성되어 컴파일 오류가 난 것이다.

 

해결방법은 2가지이다.

 

1. 자동생성되는 getter, setter 의 이름인 "get/set + 변수명" 과 다른 함수를 작성한다.

2. @JvmName 을 달아준다.

 

1번은 간단하게 함수명을 다른걸로 바꾸면 해결된다. getName() 만 피하면 되니까...

뭐 가령 getObjName()으로 변경만 해도 문제없이 실행된다.

 

2번은 중복된 JVM signature를 변경해주는 것이다. 내가 생성한 getName() 함수 위에 다음과 같이 추가해주면 된다.

inner class Person(){
    var name: String?= null
    var age: Int? = null
    @JvmName("userDefinedGetName")
    fun getName(): String?{
        return name
    }
}

@JvmName을 사용하여 userDefinedGetName으로 JVM Signature를 변경해주었다. 디컴파일하면 다음과 같다.

public final class Person {
   @Nullable
   private String name;
   @Nullable
   private Integer age;
   @Nullable
   public final String getName() {
      return this.name;
   }
   public final void setName(@Nullable String var1) {
      this.name = var1;
   }
   @Nullable
   public final Integer getAge() {
      return this.age;
   }
   public final void setAge(@Nullable Integer var1) {
      this.age = var1;
   }
   @JvmName(
      name = "userDefinedGetName"
   )
   @Nullable
   // getName() 으로 되어있던 함수명이 내가 지정해준 JvmName으로 변경되었다
   public final String userDefinedGetName() { 
      return this.name;
   }
}

 

클래스를 생성하고, 내부에 함수를 작성할때 함수명에 유의하여 작업해야함을 알았다.


참고자료

https://velog.io/@_im_ssu/JVM-signature-error-%EB%8C%80%EC%B2%98%ED%95%98%EA%B8%B0

 

JVM signature error 대처하기

부생성자에서 same JVM signature 오류가 발생한다면?

velog.io

https://codechacha.com/ko/kotlin-annotations/

 

Kotlin에서 자주 사용하는 annotation 정리

코틀린에서 자주 사용되는 @JvmName, @JvmStatic, @JvmField, @Throws, @JvmOverloads 등의 annotation들을 정리하였습니다. 코틀린은 JVM에서 동작하고 자바와 함께 사용되는 경우가 많기 때문에 이런 annotation들이

codechacha.com

 

반응형