답변:
"응용 프로그램 힙 크기 사용 가능"이라는 문구를 생각하는 두 가지 방법이 있습니다.
하드 오류가 발생하기 전에 앱에서 얼마나 많은 힙을 사용할 수 있습니까? 과
Android OS 버전과 사용자 기기 하드웨어의 제약 조건을 감안할 때 내 앱에서 얼마나 많은 힙을 사용해야 합니까?
위의 각각을 결정하는 다른 방법이 있습니다.
위 항목 1의 경우 : maxMemory()
onCreate()
다음과 같이 호출 될 수 있습니다 (예 : 기본 활동의 메소드에서).
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
이 방법은 앱 에서 사용할 수있는 총 총 바이트 수를 알려줍니다 .
위의 항목 2의 경우 : getMemoryClass()
다음과 같이 호출 할 수 있습니다.
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
이 방법은 현재 장치의 제한과 무례하게 반복 / 사이클에 강제로 적용되지 않고 다른 앱의 실행 권한을 올바르게 존중하려면 앱에서 사용해야 하는 대략 몇 메가 바이트 의 힙을 알려줍니다 귀하의 코끼리 앱이 안드로이드 자쿠지에서 목욕을하는 동안 메모리에서 플러시.onStop()
onResume()
이 구별은 내가 아는 한 명확하게 문서화되어 있지는 않지만 5 가지 Android 장치 (아래 참조) 에서이 가설을 테스트했으며 이것이 올바른 해석임을 스스로 확인했습니다.
Android의 재고 버전의 maxMemory()
경우 일반적으로 표시된 것과 동일한 수의 메가 바이트를 반환합니다 getMemoryClass()
(즉, 후자의 값의 약 백만 배).
두 가지 방법을 분기 할 수있는 유일한 상황은 CyanogenMod와 같은 Android 버전을 실행하는 루팅 된 장치에서 사용자가 각 앱에 대해 얼마나 큰 힙 크기를 허용할지 선택할 수 있습니다. 예를 들어 CM에서이 옵션은 "CyanogenMod settings"/ "Performance"/ "VM heap size"아래에 나타납니다.
참고 : 장치에 정상보다 작은 값을 선택하면이 값을 수동으로 설정하여 시스템을 관리 할 수 있다는 점에 유의하십시오.
여기에서 반환 된 값을 보여주는 내 테스트 결과입니다 maxMemory()
및 getMemoryClass()
각각에 대해 서로 다른 두 가지 (수동 설정) 힙 값을 사용하여 사이 애 노젠 모드를 실행하는 네 가지 장치에는 :
위의 것 외에도 Ice Cream Sandwich를 실행하는 Novo7 Paladin 태블릿에서 테스트했습니다. 이것은 전체 OS를 대체하지 않는 간단한 프로세스를 통해 태블릿을 근절했으며 특히 힙 크기를 수동으로 조정할 수있는 인터페이스를 제공하지 않는다는 점을 제외하고는 기본적으로 ICS의 기본 버전이었습니다.
해당 장치의 결과는 다음과 같습니다.
또한 (아래 의견에서 Kishore 당) :
그리고 (akauppi의 의견에 따라) :
cmcromance의 의견 :
그리고 (텐센트의 의견 당) :
다른 장치들
Honeycomb부터 사용할 수있는 특수 android : largeHeap = "true"매니페스트 옵션을 사용하여이 두 가지 방법을 테스트하지는 않았지만 cmcromance 및 tencent 덕분에 위에보고 된대로 일부 샘플 bigHeap 값이 있습니다.
내 기대 (위의 largeHeap 번호에 의해 지원 될 것으로 보인다)이 옵션은 뿌리 OS를 통해 수동으로 힙을 설정 유사한 효과가 것이 될 것 - 즉, 그것의 값 올릴 것이다 maxMemory()
떠나있는 동안 getMemoryClass()
혼자. 또 다른 메소드 인 getLargeMemoryClass ()가 있는데,이 메소드는 largeHeap 설정을 사용하여 앱에 허용되는 메모리 양을 나타냅니다. getLargeMemoryClass ()에 대한 설명서는 "대부분의 응용 프로그램은이 양의 메모리가 필요하지 않으며 대신 getMemoryClass () 한계를 유지해야합니다."라고 말합니다.
내가 올바르게 추측했다면, 그 옵션을 사용하면 루팅 된 OS를 통해 힙을 올린 사용자가 사용할 수있는 공간을 사용하는 것과 동일한 이점 (및 위험)이 있습니다 (즉, 앱이 추가 메모리를 사용하는 경우, 아마도 사용자가 동시에 실행하는 다른 앱과 잘 어울리지 않을 것입니다).
메모리 클래스는 8MB의 배수 일 필요는 없습니다.
위에서 알 수 있듯이 getMemoryClass()
결과는 주어진 장치 / OS 구성에 대해 변경되지 않고 maxMemory () 값은 사용자가 힙을 다르게 설정하면 변경됩니다.
내 실제 경험은 G1 (메모리 클래스 16)에서 수동으로 힙 크기로 24MB를 선택하면 메모리 사용량이 20MB로 표류 할 때도 오류없이 실행할 수 있다는 것입니다 (아마도 나는 이것을 시도하지 않았지만 24MB까지 올라갑니다.) 그러나 다른 비슷한 대형 앱은 내 앱의 돼지의 결과로 메모리에서 플러시 될 수 있습니다. 반대로, 이러한 높은 유지 관리 앱을 사용자가 포 그라운드로 가져 오면 내 앱이 메모리에서 플러시 될 수 있습니다.
따라서로 지정된 메모리 양을 넘을 수 없습니다 maxMemory()
. 그리고, 당신은해야 시도 로 지정된 한도 내에서 머물 getMemoryClass()
. 다른 방법으로 모두 실패 할 경우 메모리를 보존하는 방식으로 해당 장치의 기능을 제한하는 것이 좋습니다.
마지막으로에 지정된 메가 바이트를 넘길 계획이라면 getMemoryClass()
앱 상태를 저장하고 복원하는 데 오랜 시간과 노력을 기울이는 것이 좋습니다. 따라서 onStop()
/ onResume()
사이클이 발생할 경우 사용자 경험이 사실상 중단되지 않습니다 .
필자의 경우 성능상의 이유로 앱을 2.2 이상을 실행하는 기기로 제한하고 있으며 이는 내 앱을 실행하는 거의 모든 기기의 메모리 클래스가 24 이상임을 의미합니다. 따라서 최대 20MB의 힙을 차지하도록 설계하고 사용자가 동시에 실행할 수있는 다른 앱과 함께 내 앱이 잘 작동한다고 확신합니다.
그러나 2.2 이상의 버전의 Android를 이전 기기 (예 : G1)에로드 한 루팅 된 사용자는 항상 있습니다. 이러한 구성이 발생하면 이상적으로 maxMemory()
는 16MB보다 훨씬 더 많이 갈 수 있다고 말 하더라도 메모리 사용 을 줄일 getMemoryClass()
필요 가 있습니다. 그리고 예산 내에서 앱이 안정적으로 작동하는지 확실하게 보장 할 수 없다면 최소한 onStop()
/ onResume()
완벽하게 작동 하는지 확인하십시오 .
getMemoryClass()
위의 Diane Hackborn (hackbod)에서 알 수 있듯이 API 레벨 5 (Android 2.0)로만 다시 사용할 수 있으므로 이전 버전의 OS를 실행하는 모든 기기의 물리적 하드웨어가 설계되었다고 가정 할 수 있습니다. 16MB 이하의 힙 공간을 차지하는 앱을 최적으로 지원합니다.
이와는 대조적으로 maxMemory()
, 문서에 따르면, API 레벨 1에있는 모든 방법을 다시 볼 수 있습니다 maxMemory()
2.0 이전의 버전은 아마 16 메가 바이트 값을 반환,하지만 난 것이다 어떻게 내 (더 이상) 사이 애 노젠 모드 버전 사용자에 해당 참조 12MB만큼 낮은 힙 값을 선택할 수 있으므로 힙 제한이 낮아질 수 있으므로 maxMemory()
2.0 이전의 OS 버전에서도 값 을 계속 테스트하는 것이 좋습니다 . maxMemory()
허용되는 것보다 많은 표시가 필요한 경우이 값이 16MB보다 더 낮게 설정 될 가능성이 낮은 경우에는 실행을 거부해야 할 수도 있습니다 .
Debug.getNativeHeapSize()
트릭을 할 것 같아요. 1.0 이후로 존재했습니다.
이 Debug
클래스에는 할당 및 기타 성능 문제를 추적하기위한 많은 훌륭한 방법이 있습니다. 또한 메모리 부족 상황을 감지해야하는 경우를 확인하십시오 Activity.onLowMemory()
.
방법은 다음과 같습니다.
앱이 사용할 수있는 최대 힙 크기 얻기
Runtime runtime = Runtime.getRuntime();
long maxMemory=runtime.maxMemory();
앱에서 현재 사용중인 힙의 양 얻기
long usedMemory=runtime.totalMemory() - runtime.freeMemory();
앱이 사용할 수있는 힙의 양 (가용 메모리) 가져 오기 :
long availableMemory=maxMemory-usedMemory;
그리고 각각을 멋지게 형식화하려면 다음을 사용할 수 있습니다.
String formattedMemorySize=Formatter.formatShortFileSize(context,memorySize);
그러면 최대 힙 크기 (바이트)가 반환됩니다.
Runtime.getRuntime().maxMemory()
ActivityManager.getMemoryClass ()를 사용하고 있었지만 CyanogenMod 7 (다른 곳에서는 테스트하지 않았습니다)에서 사용자가 힙 크기를 수동으로 설정하면 잘못된 값을 반환합니다.
getMemoryClass
은 숫자가 사용 가능한 VM의 힙 크기와 같지 않을 수 있음을 의미하는 것으로 보이며 의사에 대한 문서 getNativeHeapSize
는 ... taciturn이므로 실제로 Runtime.getRuntime().maxMemory()
가장 좋은 대답 이라고 생각 합니다.
일부 작업은 Java 힙 공간 관리자보다 빠릅니다. 일정 시간 동안 작업 을 지연 시키면 메모리 공간을 확보 할 수 있습니다. 이 방법을 사용하여 힙 크기 오류를 피할 수 있습니다.
waitForGarbageCollector(new Runnable() {
@Override
public void run() {
// Your operations.
}
});
/**
* Measure used memory and give garbage collector time to free up some
* space.
*
* @param callback Callback operations to be done when memory is free.
*/
public static void waitForGarbageCollector(final Runnable callback) {
Runtime runtime;
long maxMemory;
long usedMemory;
double availableMemoryPercentage = 1.0;
final double MIN_AVAILABLE_MEMORY_PERCENTAGE = 0.1;
final int DELAY_TIME = 5 * 1000;
runtime =
Runtime.getRuntime();
maxMemory =
runtime.maxMemory();
usedMemory =
runtime.totalMemory() -
runtime.freeMemory();
availableMemoryPercentage =
1 -
(double) usedMemory /
maxMemory;
if (availableMemoryPercentage < MIN_AVAILABLE_MEMORY_PERCENTAGE) {
try {
Thread.sleep(DELAY_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
waitForGarbageCollector(
callback);
} else {
// Memory resources are availavle, go to next operation:
callback.run();
}
}
AvailableMemoryPercentage
공식에 따르면 : 현재 사용 가능한 장치의 메모리 양. MIN_AVAILABLE_MEMORY_PERCENTAGE
가비지 콜렉터가 작업을 수행하기를 기다리는 임계 값 인 사용자 정의 매개 변수입니다.
ASUS Nexus 7 (2013) 32Gig : getMemoryClass () = 192 maxMemory () = 201326592
Nexus 7에서 게임 프로토 타이핑하는 실수를 저지른 다음 아내의 일반 4.04 태블릿 (메모리 클래스 48, 최대 메모리 50331648)에서 거의 즉시 메모리 부족을 발견했습니다.
메모리 클래스가 부족하다고 판단되면 더 적은 리소스를로드하도록 프로젝트를 재구성해야합니다.
Java에서 현재 힙 크기를 보는 방법이 있습니까? (디버깅 할 때 logCat에서 명확하게 볼 수 있지만 currentheap> (maxmemory / 2) 고품질 비트 맵을 언로드하는 경우와 같이 코드에서 적응시키는 방법을 원합니다.
프로그래밍 방식으로 또는 개발 및 디버깅 중입니까? 후자의 경우 Eclipse의 DDMS 관점에서 해당 정보를 볼 수 있습니다. 에뮬레이터 (연결된 실제 전화 일 수도 있음)가 실행 중이면 왼쪽의 창에 활성 프로세스가 나열됩니다. 선택할 수 있으며 힙 할당을 추적하는 옵션이 있습니다.
Runtime rt = Runtime.getRuntime();
rt.maxMemory()
값은 b
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
am.getMemoryClass()
값은 MB입니다
rt
? 어디에 선언되어 있습니까?