моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Перегрузка памяти означает создание и уничтожение большого количества объектов за короткий период времени, что приводит к частым действиям по сборке мусора (сборке мусора, GC). Эта частая активность сборщика мусора отнимает много ресурсов ЦП и может привести к задержкам работы приложений или снижению производительности.
Производительность: кривая памяти неровная.
Утечка памяти происходит, когда приложение хранит ссылки на объекты, которые больше не нужны, из-за чего эти объекты не могут быть переработаны сборщиком мусора, тем самым занимая пространство памяти, которое могло бы быть освобождено. Со временем утечки памяти приводят к тому, что доступной памяти становится все меньше и меньше, что в конечном итоге может привести к сбоям приложений или снижению производительности.
Переполнение памяти происходит, когда приложение пытается выделить больше места в памяти, но система не может удовлетворить запрос, поскольку памяти для выделения уже недостаточно. Обычно это приводит к тому, что приложение генерирует исключение OutOfMemoryError.
Структура памяти Java: куча, стек виртуальной машины, область методов, счетчик программ, стек локальных методов.
Алгоритм переработки памяти Java:
Недостатки алгоритма очистки-маркировки: Маркировка и очистка неэффективны и приводят к образованию большого количества прерывистых фрагментов памяти.
Алгоритм репликации: прост в реализации и эффективен в эксплуатации. Недостатки: Потеряна половина места.
Алгоритм компактной пометки: избегайте фрагментации памяти, вызванной очисткой пометок, и избегайте пустой траты места алгоритма копирования.
Эластичное распределение памяти Android, значение выделения и максимальное значение зависят от конкретных устройств.
Алгоритм переработки Dalvik и алгоритм переработки ART — это механизмы сбора мусора, используемые для управления памятью в операционной системе Android.
Алгоритм переработки Dalvik:
Алгоритм переработки предметов искусства:
Механизм ЛМК:
public class ShakeActivity extends AppCompatActivity {
private static Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
String str = "";
for (int i = 0; i < 10000000; i++) {
str += i;
}
mHandler.sendEmptyMessageDelayed(1, 30);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shake);
}
public void startClick(View view) {
mHandler.sendEmptyMessage(1);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
Профилировщик памяти может просмотреть распределение памяти, нажмите «Записать выделение Java/Kotlin».
Смысл вышесказанного:
Следующие значения:
malloc()
илиnew
Количество объектов, выделенных оператором.free()
илиdelete
Количество объектов, освобожденных оператором.Анализ изображения выше:
Значения «Выделение» и «Освобождение» в этой области относительно схожи, а «Мелкий размер» относительно велик, что указывает на то, что объекты могут часто создаваться и уничтожаться.
После щелчка вы можете просмотреть информацию о стеке вызовов и в сочетании с кодом сделать вывод о проблеме дрожания памяти в обработчике.
public class CallbackManager {
public static ArrayList<Callback> sCallbacks = new ArrayList<>();
public static void addCallback(Callback callback) {
sCallbacks.add(callback);
}
public static void removeCallback(Callback callback) {
sCallbacks.remove(callback);
}
}
public class LeakActivity extends AppCompatActivity implements Callback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leak);
ImageView imageView = findViewById(R.id.imageView);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.splash);
imageView.setImageBitmap(bitmap);
CallbackManager.addCallback(this);
}
@Override
public void onOperate() {
}
}
Добавьте зависимые библиотеки:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
После того, как произойдет утечка памяти, LeakCanary сгенерирует соответствующую информацию и автоматически выгрузит ее:
Как видно из рисунка выше: LeakActivity имеет утечку памяти, и отображается связь цепочки ссылок.
Конечно, вы также можете создать файл hprof и просмотреть конкретную информацию с помощью инструмента Profiler:
Как видно из рисунка выше: произошло 10 точек утечки, включая LeakActivity. Нажмите LeakActivity, чтобы просмотреть объект утечки памяти и проверить цепочку ссылок. Видно, что он удерживается ArrayList.
Если вы не освободите ресурсы изображения после использования Bitmap, это легко вызватьУтечка памяти, приводящая к переполнению памяти。
Переработка памяти:
Bitmap.recycle()
Выполните переработку растрового изображения.Конфигурация растрового пикселя:
Конфигурация | Занимаемый размер байта (байт) | иллюстрировать |
---|---|---|
АЛЬФА_8 | 1 | один прозрачный канал |
РГБ_565 | 2 | Простой оттенок RGB |
ARGB_8888 | 4 | 24-битный настоящий цвет |
RGBA_F16 | 8 | Android 8.0 Новый (HDR) |
Рассчитаем память, занимаемую Btimap:
Проблема с файлом ресурсов:
Тестовый код:
private void printBitmap(Bitmap bitmap, String drawable) {
String builder = drawable +
" Bitmap占用内存:" +
bitmap.getByteCount() +
" width:" +
bitmap.getWidth() +
" height:" +
bitmap.getHeight() +
" 1像素占用大小:" +
getByteBy1px(bitmap.getConfig());
Log.e("TAG", builder);
}
private int getByteBy1px(Bitmap.Config config) {
if (Bitmap.Config.ALPHA_8.equals(config)) {
return 1;
} else if (Bitmap.Config.RGB_565.equals(config)) {
return 2;
} else if (Bitmap.Config.ARGB_8888.equals(config)) {
return 4;
}
return 1;
}
// 逻辑密度
float density = metrics.density;
// 物理密度
int densityDpi = metrics.densityDpi;
Log.e("TAG", density + "-" + densityDpi);
// 1倍图
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.splash1);
printBitmap(bitmap1, "drawable-mdpi");
// 2倍图
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.splash2);
printBitmap(bitmap2, "drawable-xhdpi");
// 3倍图
Bitmap bitmap3 = BitmapFactory.decodeResource(getResources(), R.drawable.splash3);
printBitmap(bitmap3, "drawable-xxhdpi");
// 4倍图
Bitmap bitmap4 = BitmapFactory.decodeResource(getResources(), R.drawable.splash4);
printBitmap(bitmap4, "drawable-xxxhdpi");
// drawable
Bitmap bitmap5 = BitmapFactory.decodeResource(getResources(), R.drawable.splash);
printBitmap(bitmap5, "drawable");
/*
3.0-480
drawable-mdpi Bitmap占用内存:37127376 width:2574 height:3606 1像素占用大小:4
drawable-xhdpi Bitmap占用内存:9281844 width:1287 height:1803 1像素占用大小:4
drawable-xxhdpi Bitmap占用内存:4125264 width:858 height:1202 1像素占用大小:4
drawable-xxxhdpi Bitmap占用内存:2323552 width:644 height:902 1像素占用大小:4
drawable Bitmap占用内存:37127376 width:2574 height:3606 1像素占用大小:4
*/
проиллюстрировать:
1dp на устройствах mdpi1px, 1dp на устройствах xhdpi2px, 1dp==3px на устройстве xxhdpi.
Следовательно, текущее устройство - xxhdpi, поэтому ширина той же картинки под ресурсом xxhdpi равна 858, под ресурсом mdpi она будет увеличена в 3 раза и ширина равна 2574, а под ресурсом xhdpi она будет увеличена в 1,5 раза и ширина 1287.