In uno dei miei precedenti put up, abbiamo discusso Come trovare al meglio le perdite di memoria E le ragioni dietro di loro. È meglio utilizzare uno strumento focalizzato e moderno come Heaphero per rilevare errori OUTOFMORY e molti altri colpi di bottiglia delle prestazioni, in quanto può individuare i veri colpevoli e suggerire modi per ottimizzare l’uso delle risorse di elaborazione.
Sopra, puoi vedere che ci sono alcune migliaia di oggetti di byte()
, String
, int()
, ecc.
Discutiamo alcuni modi di riparare OutOfMemoryErrors
in Java. Puoi vedere quali correzioni sono applicabili nel tuo situation/codice e applicarle per salvare la memoria ed eseguire meglio i tuoi programmi. Alcuni dei modi discussi di seguito possono sembrare banali per te, ma ricorda che alcune piccole correzioni possono sommarsi a un grande guadagno.
1. Usa byteBuffer da java.nio
Invece di allocare array di byte di grandi dimensioni che possono essere sottoutilizzati, consente l’allocazione di memoria diretta (Bytebuffer.allocatedirect (dimensione)) per ridurre la pressione GC ed evitare Allocazioni di heap non necessarie.
Se hai a che fare con array di byte in crescita dinamicamente, evita di iniziare con un array inutilmente grande.
ByteBuffer buffer = ByteBuffer.allocateDirect(1024); // Allocates 1KB in off-heap reminiscence
Advert esempio, invece di:
ByteArrayOutputStream baos = new ByteArrayOutputStream(10000);// Too massive
Lascia che Java gestisca il ridimensionamento quando necessario perché JVMS e JRES sono continuamente migliorati per consumare risorse minime e gestire bene il loro ciclo delle risorse.
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Begins small and grows as wanted
O fornire una piccola dimensione iniziale se si conosce in anticipo la lunghezza minima richiesta.
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048); // Begins small and grows as wanted
2. Usa i flussi per elaborare i dati in blocchi
Invece di leggere un intero file in memoria usando un enorme array di byte,
Advert esempio, non usare:
byte() knowledge = Information.readAllBytes(Path.of("myLargeFile.txt")); // Hundreds total file into reminiscence
Invece, prova questo:
attempt (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myLargeFile.txt"));
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte() buffer = new byte(2048); // Learn in smaller chunks
int bytesRead;
whereas ((bytesRead = bis.learn(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
byte() knowledge = baos.toByteArray();
}
3. Utilizzo della nuova interfaccia di memoria in Java 21
Puoi accedere alla memoria off-heap o sul cano Funzione e memoria estranea (FFM) API in modo efficiente. Introduce il concetto di un Enviornment. Utilizzi un’enviornment per allocare un segmento di memoria e controllare il ciclo di vita dei segmenti di memoria nativi.
SegmentAllocator
da Venture Panama (Java 21) consente un migliore controllo sull’allocazione della memoria.
Invece di array di grandi dimensioni basati su heap, allocare la memoria usando MemorySegment
che riduce la collezione di immondizia in alto.
Quando usi il try-with-resources
l’enviornment sarà chiusa non appena il blocco di prova termina, tutti i segmenti di memoria associati al suo ambito sono invalidati e le regioni di memoria che le sostengono vengono deallocate.
Per esempio:
import java.lang.overseas.*;
String s = "My LARGE ......... LARGE string";
attempt (Enviornment enviornment = Enviornment.ofConfined()) {
// Allocate off-heap reminiscence
MemorySegment nativeText = enviornment.allocateUtf8String(s);
// Entry off-heap reminiscence
for (int i = 0; i
4. Usa oggetti singleton ove possibile
Alcune classi di utilità non devono essere istanziate per richiesta; Può esserci solo un’unica istanza statica per l’intera applicazione/sessione.
Per esempio, Scarshaller e marshaller. Gli sgradevoli fanno parte delle specifiche JAXB. Sono usati per convertire i dati XML in oggetti Java nelle sue rappresentazioni XML. Allo stesso modo, i marshaller vengono utilizzati per convertire gli oggetti Java in rappresentazioni XML. Questi aiutano nell’elaborazione dei dati XML nei programmi Java mappando elementi XML e attributi a campi e proprietà Java, utilizzando annotazioni Java.
Se guardi da vicino il Jaxbcontext classe, vedrai che ha metodi staticicreateUnmarshaller()
/ createMarshaller()
Metodi, che è una chiara indicazione che questi potrebbero essere gestiti meglio come singola istanza statica per l’intera applicazione/sessione.
5. Usa l’ambito di singleton nelle applicazioni basate su primavera
In questo modo, il contenitore crea una singola istanza di quel bean per l’intera applicazione da condividere, ove possibile, mantenendo intatta la logica aziendale.
Se codifica un’applicazione Internet, ricorda che il @utility
L’ambito crea l’istanza del fagiolo per il ciclo di vita di a ServletContext
IL @request
L’ambito crea un’istanza di fagioli per una singola richiesta HTTP, mentre l’ambito della sessione crea un’istanza di fagioli per una particolare sessione HTTP.
@Bean
@Scope("singleton")
public SomeService someService() {
return new SomeService();
}
6. Utilizzare various più veloci ed efficienti dalla memoria a raccolte popolari
Utilizzo Collections.singletonmap E Collections.singletonlist (per piccole collezioni)
Advert esempio, se hai bisogno solo di una singola coppia o oggetto di valore chiave, evitare di utilizzare un hashmap completo o un arraylist, che hanno un sovraccarico.
Utilizzo Arraydeque Invece di Linkedlist
Linkedlist ha un alto livello di memoria a causa della memorizzazione di puntatori di nodi (riferimenti successivi/prev). Invece, usa Arraydequeche è più veloce ed efficiente dalla memoria.
import java.util.ArrayDeque;
ArrayDeque deque = new ArrayDeque();
deque.add(22);
deque.removeFirst();
Utilizzo Map.of () E Record.of () (Collezioni immutabili)
Se non è necessario modificare una raccolta, utilizzare collezioni immutabili, che sono compatte e ottimizzate.
Map map = Map.of("A", 1, "B", 2);
Record checklist = Record.of("X", "Y", "Z");
Utilizzo Debolehashmap per la memorizzazione nella cache
Se si archiviano dati temporanei in un hashmap, potrebbe non essere mai raccolto, quindi usa Debolehashmapche rimuove automaticamente le voci quando le chiavi non vengono più referenziate.
7. Chiudi gli oggetti non appena la loro utilità
Strete di rete non chiusi, flussi I/O, connessioni di database e oggetti di database/rete continuano a utilizzare le risorse di memoria e CPU, aggiungendo al costo di esecuzione dell’applicazione.
Abbiamo discusso di alcuni modi testati nel tempo per affrontare gli errori di OUTOFMORY in Java.
I tuoi commenti sono benvenuti.