메모리 관리

대부분의 Java 개발자들이 궁금해하는 첫 번째 질문은 Java에는 가비지 컬렉션이 있고 Objective-C에 기본적으로 없는 것이기 때문에 J2ObjC에서 메모리 관리를 어떻게 구현하는가입니다. iOS에는 참조 집계와 자동 참조 계산 (ARC)이라는 두 가지 메모리 관리 방법이 있습니다.

J2ObjC는 선택한 방법에 따라 다른 메모리 관리 코드를 생성합니다. ARC를 사용하는 코드를 생성하려면 -use-arc 옵션으로 번역합니다. 기본적으로 수동 참조 집계를 사용합니다.

참조 수 계산

참조 계산 방법은 객체 소유권을 명시합니다. 메서드는 객체를 생성할 때 해당 객체를 해제할 때까지 객체를 소유합니다. 다른 메서드에서 객체를 수신할 때 수신 메서드는 메서드가 반환된 후 참조해야 하는 경우 객체를 보관합니다. 메서드가 더 이상 객체를 참조할 필요가 없으면 객체를 해제해야 합니다. 객체의 보관 수가 0이면 메모리가 해제되고 객체가 더 이상 유효하지 않습니다. 객체가 해제되면 해당 transactionloc() 메서드가 호출되어 인스턴스 변수의 소유권이 해제됩니다.

이 기법의 한 가지 문제는 객체의 소유권을 이전하는 방법입니다. 예를 들어 팩토리 메서드를 호출하여 객체를 만들 수 있습니다. 팩토리 메서드가 객체를 반환하기 전에 해제하면 (더 이상 객체를 소유하려고 하지 않기 때문에) 이 객체는 호출 메서드가 유지하기 전에 해제됩니다.

객체의 소유권을 이전하기 위해 메서드는 출시 메시지 대신 자동 해제 메시지를 전송합니다. 이 메시지는 출시 메시지를 지연시킵니다. 따라서 팩토리 메서드는 반환할 객체를 만들고 객체를 무효화하지 않고 소유권을 포기할 수 있습니다. 일정한 간격으로 (예: iOS 애플리케이션에서 각 이벤트 루프가 반복된 후) 자동 해제 풀이 '드레이닝'됩니다. 즉, 해당 풀의 모든 객체가 지연된 출시 메시지로 전송됩니다. 보관 수가 0으로 떨어지는 모든 객체는 정상적으로 해제됩니다.

메모리 관리는 개발자가 부담하므로 참조 집계 메서드를 사용하면 메모리 누수가 발생하기 쉽습니다. 하지만 Apple은 이 문제를 최소화하기 위해 J2ObjC에서 구현하는 몇 가지 권장사항을 권장합니다.

메모리 누수를 감지하기 위한 런타임 및 도구 지원도 있습니다. Objective-C 런타임은 애플리케이션이 종료될 때 감지된 누수를 보고합니다. 이는 J2ObjC가 JUnit 테스트를 실행 가능한 바이너리로 변환하는 한 가지 이유입니다. Xcode는 Clang을 사용하며 이 컴파일러는 메모리 문제에 대한 뛰어난 정적 분석을 제공합니다. Xcode는 Analyze 명령어로 이를 사용할 수 있습니다.

자동 참조 계산 (ARC)

ARC는 Apple에서 권장하는 메모리 관리 방법입니다. 참조 계산의 책임이 컴파일러로 옮겨지고 컴파일 중에 적절한 keep, release, autorelease 메서드가 추가됩니다. ARC는 iOS 5 이상을 실행하는 기기의 약한 참조를 지원합니다.

프로젝트에서 번역된 코드에 ARC를 사용하는 것이 좋습니다. 트랜스코딩된 Objective-C 코드는 손으로 작성한 Objective-C 코드와 같습니다. ARC를 사용하면 개발자가 과도 해제 또는 과소 참조와 같은 일반적인 메모리 관련 오류를 방지하여 메모리 관리를 더 간소화하고 오류 발생 가능성을 줄일 수 있습니다.

기본적으로 ARC는 예외 안전성이 없습니다. 특히 예외가 발생하면 메모리를 누출합니다. 예외는 자바에서 더 일반적이고 일반적으로 복구할 수 있으므로 문제가 될 수 있습니다. 원호로 컴파일할 때 -fobjc-arc-exceptions를 사용하면 허용 가능한 성능 비용으로 누수가 해결됩니다.

또한 새 프로젝트에서 직접 작성한 Objective-C 코드에 ARC를 사용하고 프로파일링 데이터에 실제 성능 문제가 나타나는 경우에만 수동 참조 계산으로 대체하는 것이 좋습니다. ARC 코드와 비 ARC 코드는 모두 문제없이 동일한 앱에 컴파일 및 링크할 수 있습니다.

취약한 참조

필드는 트랜스파일러가 Objective-C 약한 참조 시맨틱스를 따르는 필드를 생성하는 데 사용하는 com.google.devtools.j2objc.Weak로 주석을 달 수 있습니다. 참조 횟수를 사용하는 경우, 이는 필드가 초기화될 때 유지되지 않고 포함된 인스턴스가 해제될 때 자동으로 해제된다는 것을 의미합니다. ARC를 사용하면 약한 필드는 __unsafe_unretained 주석으로 표시되고 관련 속성은 약하게 선언됩니다.

경우에 따라 내부 클래스 인스턴스가 외부 인스턴스와 함께 참조 주기를 형성합니다. 여기서 com.google.devtools.j2objc.WeakOuter 주석은 내부 클래스를 표시하는 데 사용되므로 외부 클래스 참조는 위에 설명된 대로 처리됩니다. 내부 클래스의 다른 필드는 이 주석의 영향을 받지 않습니다.

J2ObjC도 WeakReference 클래스를 지원하므로 이 클래스를 사용하는 자바 코드는 변환 시 동일한 방식으로 작동합니다. WeakReference는 본질적으로 JVM에서 비확정적입니다. 예측 가능성을 유지하면서 메모리 누수를 방지하려는 애플리케이션은 대신 @Weak@WeakOuter를 사용해야 합니다.

메모리 관리 도구