2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Muistin tuhoaminen tarkoittaa suuren määrän esineiden luomista ja tuhoamista lyhyessä ajassa, mikä johtaa usein tapahtuvaan roskien keräilyyn (Garbage Collection, GC). Tämä toistuva GC-toiminto vie paljon suoritinresursseja ja voi aiheuttaa sovelluksen viiveitä tai suorituskyvyn heikkenemistä.
Suorituskyky: Muistikäyrä on rosoinen.
Muistivuoto tapahtuu, kun sovelluksessa on viittauksia objekteihin, joita ei enää tarvita, jolloin roskankerääjä ei pysty hyödyntämään näitä objekteja ja vievät näin muistitilaa, joka olisi voinut vapautua. Ajan myötä muistivuodot johtavat yhä vähemmän käytettävissä olevaan muistiin, mikä voi lopulta johtaa sovellusten kaatumiseen tai suorituskyvyn heikkenemiseen.
Muistin ylivuoto tapahtuu, kun sovellus yrittää varata lisää muistitilaa, mutta järjestelmä ei voi täyttää pyyntöä, koska varattavaa muistitilaa ei enää ole tarpeeksi. Tämä saa yleensä sovelluksen heittämään OutOfMemoryError-poikkeuksen.
Java-muistirakenne: pino, virtuaalikonepino, menetelmäalue, ohjelmalaskuri, paikallinen menetelmäpino.
Java-muistin kierrätysalgoritmi:
Merkintojen tyhjennys-algoritmin haitat: Merkintä ja tyhjennys eivät ole tehokkaita ja tuottavat suuren määrän epäjatkuvia muistin fragmentteja.
Replikointialgoritmi: yksinkertainen toteuttaa ja tehokas ajaa. Haitat: puolet tilasta hukkaan.
Mark-compact-algoritmi: vältä mark-cleanin aiheuttamaa muistin pirstoutumista ja vältä kopiointialgoritmin tilan tuhlaamista.
Tietyt laitteet vaikuttavat Android-muistin elastiseen varaukseen, varausarvoon ja enimmäisarvoon.
Dalvikin kierrätysalgoritmi ja ART-kierrätysalgoritmi ovat molemmat roskankeräysmekanismeja, joita käytetään muistin hallintaan Android-käyttöjärjestelmässä.
Dalvikin kierrätysalgoritmi:
Taiteen kierrätysalgoritmi:
LMK-mekanismi:
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);
}
}
Memory Profiler voi tarkastella muistivarauksia napsauttamalla "Tallenna Java/Kotlin-varaukset".
Yllä olevan merkitys:
Seuraavat merkitykset:
malloc()
tainew
Operaattorin osoittamien kohteiden määrä.free()
taidelete
Operaattorin jakamien kohteiden määrä.Ylläolevan kuvan analyysi:
Varausten ja jakamisten arvot tällä alueella ovat suhteellisen samanlaisia, ja matala koko on suhteellisen suuri, mikä osoittaa, että esineitä voidaan luoda ja tuhota usein.
Napsautuksen jälkeen voit tarkastella puhelupinon tietoja, ja yhdessä koodin kanssa voit päätellä, että Käsittelijässä on muistin värinäongelma.
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() {
}
}
Lisää riippuvaisia kirjastoja:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
Kun muistivuoto tapahtuu, LeakCanary luo asiaankuuluvat tiedot ja tyhjentää ne automaattisesti:
Kuten yllä olevasta kuvasta voidaan nähdä: LeakActivityssä on muistivuoto, ja viiteketjun suhde näytetään.
Voit tietysti myös luoda hprof-tiedoston ja tarkastella tiettyjä tietoja Profiler-työkalun kautta:
Kuten yllä olevasta kuvasta näkyy: 10 vuotokohtaa, mukaan lukien LeakActivity, voit tarkastella muistivuotoja ja tarkistaa viiteketjun.
Jos et vapauta kuvaresursseja bittikartan käytön jälkeen, se on helppo aiheuttaaMuistivuoto, joka johtaa muistin ylivuotoon。
Muistin kierrätys:
Bitmap.recycle()
Suorita Bitmap-kierrätys.Bittikarttapikselin kokoonpano:
Konfig | Varatun tavun koko (tavu) | havainnollistaa |
---|---|---|
ALPHA_8 | 1 | yksi läpinäkyvä kanava |
RGB_565 | 2 | Yksinkertainen RGB-sävy |
ARGB_8888 | 4 | 24-bittinen todellinen väri |
RGBA_F16 | 8 | Android 8.0 New (HDR) |
Laske Btimapin käyttämä muisti:
Resurssitiedostoongelma:
Testikoodi:
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
*/
havainnollistaa:
1dp mdpi-laitteissa1px, 1dp xhdpi-laitteissa2px, 1dp==3px xxhdpi-laitteessa.
Siksi nykyinen laite on xxhdpi, joten saman kuvan leveys xxhdpi-resurssin alla on 858, mdpi-resurssin alla se suurennetaan 3-kertaiseksi ja leveys on 2574, ja xhdpi-resurssin alla 1,5-kertainen ja leveys on 1287.