JavaRush /Java Blog /Random-IT /Pausa caffè #88. Il potere dei metadati: come lavorare co...

Pausa caffè #88. Il potere dei metadati: come lavorare con lo spaghetti code. Garbage Collection in Java: come funziona e quali sono i suoi vantaggi

Pubblicato nel gruppo Random-IT

Il potere dei metadati: come lavorare con lo spaghetti code

Fonte: Hackernoon Cerchiamo tutti di utilizzare approcci comuni e modelli conosciuti per creare un'applicazione con il minimo sforzo e il massimo impatto. Disponiamo di eccellenti librerie e potenti framework che eseguono operazioni di routine per noi. Usiamo tutto questo per concentrarci solo sulla logica aziendale. Tuttavia, questa ricerca ci porta spesso allo spaghetti code, soprattutto quando si tratta di implementare una funzione senza una soluzione pronta. In questo articolo voglio condividere con te uno strumento potente che, secondo la mia esperienza, non tutti gli sviluppatori apprezzano. Questo strumento è presente nella maggior parte dei linguaggi di programmazione ed è molto spesso utilizzato in molti framework: annotazioni. Pausa caffè #88.  Il potere dei metadati: come lavorare con lo spaghetti code.  Garbage Collection in Java: come funziona e quali sono i suoi vantaggi - 1

Ti piacciono gli spaghetti?

Diamo un'occhiata a un esempio in cui mi sono imbattuto un paio di anni fa. Avevo bisogno di analizzare un foglio di calcolo Excel per inserire i dati analizzati in un database. Volevo anche raccogliere alcuni dati dal database e creare un foglio di calcolo. Per l'implementazione ho utilizzato la nota libreria Java - Apache POI. L'API della libreria semplifica il tuo lavoro perché ti consente di creare manualmente un foglio, una riga, una cella e altri elementi. Questo è molto buono, ma quando è necessario generare vari fogli di calcolo Excel, il codice diventa completamente illeggibile e insostenibile. Di conseguenza, come di solito accade, la prima versione dell'applicazione risulta essere semplicemente terribile. L'implementazione consisteva in una classe di dati che rappresentava una stringa con tutti i campi necessari per l'analisi. C'era anche un parser in cui i campi Excel venivano analizzati cella per cella e inseriti in un'istanza di classe dati appena creata. All'inizio il programma funzionava benissimo e faceva ciò che gli veniva richiesto. I problemi sono iniziati quando è arrivato il momento di apportare alcune modifiche; il codice non è stato letto. Anche io, che ho scritto questo codice, non sono riuscito a trovare un posto adatto dove inserire nuove righe per implementare la nuova funzione di cui avevo bisogno.

Salvataggio nelle annotazioni

Salvata l'applicazione da questo codice spaghetti di annotazione. Per eliminare il codice non supportato, avevo bisogno di spostare la logica per determinare quale colonna analizzare, che tipo di dati conteneva una cella e tutto il resto in una posizione diversa. Per fare ciò, ho creato un'annotazione in cui ho specificato il nome della colonna per ciascun campo della classe. Nell'annotazione ho aggiunto anche una variabile che permette di selezionare il colore e il carattere della cella. Pertanto, il codice nella classe di analisi è stato notevolmente ridotto. Solo un processore ha creato dinamicamente il foglio di calcolo in base ai parametri presi dalle annotazioni. È stata una vittoria. Quindi, per apportare eventuali modifiche all'applicazione, dovevo semplicemente creare una classe con annotazioni. La soluzione ricordava la libreria Jackson, che analizza JSON utilizzando le annotazioni, e penso che non sia necessario dire quanto siano convenienti le librerie Jackson o simili.
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnExcel {

    String name() default "";

    int position();

    ExcelColumnDataFormat cellTypePattern() default ExcelColumnDataFormat.NONE;

    IndexedColors cellColor() default IndexedColors.AUTOMATIC;

    ExcelTotalFormula total() default ExcelTotalFormula.NONE;

}
ColumnExcel columnExcel = field.getAnnotation(ColumnExcel.class);
Man mano che l'applicazione si evolveva, riceveva una nuova annotazione che poteva essere utilizzata per creare una cella in un foglio di calcolo con una funzione al suo interno. È possibile moltiplicare, sottrarre vari campi e utilizzare qualsiasi funzione comune di Excel. Ho anche aggiunto una riga totale per mostrare la somma per colonna. E ho fatto tutto questo semplicemente modificando leggermente il parser principale e aggiungendo semplicemente annotazioni alle classi.
@ColumnExcel(
            name = "Views",
            position = 4,
            total = ExcelTotalFormula.SUM)
    private BigDecimal variableC;

    @ColumnExcelFormula(
            name = "Conversion",
            position = 5,
            cellTypePattern = CellDataTypeFormatPattern.PERCENTAGE
    )
    public String variableD(int rowNumber) {
        return new CellAddress(rowNumber, 4).formatAsString() + "*"
		+ new CellAddress(rowNumber, 2).formatAsString();
    }

    @ColumnExcelTotalFormula(position = 4, cellTypePattern = CellDataTypeFormatPattern.RUR)
    public static String getVariableCTotalFormula(int firstRowNum, int lastRowNum) {
        return "SUM( " + new CellAddress(firstRowNum, 4).formatAsString() + ":"
		+ new CellAddress(lastRowNum, 4).formatAsString() + ")";
    }

Garbage Collection in Java: come funziona e quali sono i suoi vantaggi

Fonte: Dev.to Garbage collection significa distruggere o ripulire oggetti inutilizzati in memoria. Java gestisce la deallocazione della memoria automaticamente perché una volta creato un oggetto, utilizza parte della memoria nell'heap. Pausa caffè #88.  Il potere dei metadati: come lavorare con lo spaghetti code.  Garbage Collection in Java: come funziona e quali sono i suoi vantaggi - 2

Come funziona?

Prima di Java, il linguaggio di programmazione più popolare era C o C++. Se parli queste lingue, dovresti sapere che gestiscono manualmente la propria memoria. Ad esempio, C dispone di metodi come calloc() , malloc() e realloc() che ti permetteranno di utilizzare la memoria buffer. Devi determinare la quantità di memoria necessaria per il tuo programma e specificare cosa viene chiamato da questa API. È quindi possibile ottenere un buffer di memoria per creare un nodo di elenco collegato o qualcos'altro. Quando il tuo programma termina, ad un certo punto, sei anche responsabile della pulizia della memoria. Quindi una grande applicazione scritta in C continua ad allocare memoria buffer e talvolta si dimentica di svuotarla. Ciò alla fine causa perdite di memoria e molti problemi nell'applicazione. A differenza di C e C++, il linguaggio Java prevede la gestione automatica della memoria tramite un thread chiamato garbage collector. Il suo scopo principale è liberare memoria dall'heap distruggendo oggetti inaccessibili. Il Garbage Collector viene sempre eseguito in background.

Cosa sono gli oggetti inaccessibili in Java?

Quando un oggetto ha la possibilità di avviare la garbage collection? Se sono presenti oggetti inaccessibili, quelli per i quali non esistono collegamenti attivi. Vediamo un esempio:
public static void main(String[] args)
{
// StringBuffer object sb is not eligible for garbage collection
StringBuffer sb = new StringBuffer("Flower Brackets");
System.out.println(sb);
// StringBuffer object sb is eligible for garbage collection
sb = null;
}
Nel metodo main ho creato un oggetto StringBuffer e un riferimento ad esso. A questo punto, l' oggetto StringBuffer non è idoneo per la Garbage Collection. Ora imposterò l' oggetto StringBuffer su "null". L'oggetto è ora idoneo per la Garbage Collection e diventa un oggetto inaccessibile nella memoria heap. Cioè, la garbage collection generalmente funziona nei casi in cui gli oggetti diventano inaccessibili. Ciò significa che gli oggetti vengono solitamente creati nel contesto di un "blocco if" o di un metodo. Pertanto, gli oggetti escono dall'ambito una volta completata l'esecuzione del metodo e possono essere eliminati dal Garbage Collector. Poiché i riferimenti da vecchi oggetti a nuovi esistono in numero limitato, ciò significa che gli oggetti presenti nell'applicazione da molto tempo di solito non sono oggetti appena creati. Ecco un paio di termini con cui dovremmo avere familiarità; uno di questi è un oggetto vivo. È un oggetto in un'applicazione a cui fa riferimento un altro oggetto nella stessa applicazione. C'è anche un oggetto “morto”. Un oggetto morto è un oggetto inaccessibile che viene creato durante una chiamata al metodo e, una volta completata la chiamata al metodo, l'oggetto esce dal contesto e rimane semplicemente nell'heap.

Quando un oggetto è idoneo per la Garbage Collection?

Se un oggetto non dispone di alcuna variabile di riferimento, l'oggetto è idoneo per la Garbage Collection.

Come rendere un oggetto disponibile per la garbage collection?

Di seguito sono riportati diversi modi:
  1. null reference variable
    Student obj = new Student();
    obj = null;

  2. re-assign reference variable
    Student obj1 = new Student();
    Student obj2 = new Student();
    obj1 = obj2;

  3. reate anonymous object
    new Student();

    Una volta reso disponibile al Garbage Collector, un oggetto non viene immediatamente distrutto.

Quando la Java Virtual Machine esegue il Garbage Collector, solo l'oggetto viene distrutto. NOTA: Il Garbage Collector raccoglie solo oggetti creati utilizzando la parola chiave "new", per gli oggetti senza la parola chiave "new", utilizzare il metodo finalize() . Esistono diversi metodi per eseguire il Garbage Collector nella Java Virtual Machine:
  1. Metodo System.gc()

  2. metodo finalize()

  3. Metodo Runtime.getRuntime().gc()

Il metodo statico gc() si trova nella classe System . Questo metodo chiede alla JVM di chiamare il garbage collector. Vediamo come un'applicazione Java chiama il garbage collector utilizzando il metodo gc() .
public class GarbageCollector
{
public static void main(String[] args)
{
Employee obj1 = new Employee();
Employee obj2 = new Employee();
obj1 = null;
obj2 = null;
System.gc();
}
public void finalize()
{
System.out.println("object garbage collected");
}
}
Risultato:
oggetto Garbage Collection oggetto Garbage Collection raccolto
Il metodo finalize() viene chiamato subito prima che l'oggetto venga ripulito. Questo metodo è definito nella classe Object :
protected void finalize() throws Throwable
  1. Il metodo Finalize viene utilizzato per chiudere la connessione al database.

  2. Questo metodo viene chiamato dal Garbage Collector, non dalla JVM.

  3. Dobbiamo sovrascrivere il metodo finalize() . Perché ha un'implementazione vuota.

  4. Viene chiamato solo una volta per oggetto.

Il metodo getRuntime().gc() è presente nella classe runtime. Restituisce l' oggetto Runtime associato all'applicazione Java corrente. Diamo un'occhiata a questo metodo in un programma Java.
public class Demo
{
public static void main(String[] args)
{
Demo obj1 = new Demo();
Demo obj2 = new Demo();
// nullifying reference variable
obj1 = null;
// nullifying reference variable
obj2 = null;
// running Garbage Collector
Runtime.getRuntime().gc();
}
@Override
protected void finalize() throws Throwable
{
System.out.println("Garbage collector called");
System.out.println("Object garbage collector: " + this);
}
}
Risultato:
Garbage collector chiamato Object Garbage Collector: Demo@2130772 Garbage collector chiamato Object Garbage Collector: Demo@cd4e940

Vantaggi della raccolta dei rifiuti:

  1. La raccolta dei rifiuti in Java avviene automaticamente, il che ci risparmia l'onere aggiuntivo di liberare la memoria utilizzata. Ciò rende la memoria del programma Java più efficiente.
  2. La Garbage Collection garantisce l'integrità del programma.
  3. Non è necessario scrivere alcun codice aggiuntivo poiché il garbage collector fa parte della JVM.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION