Maison Java JavaQuestions d'entretien Questions et réponses d'entretien Java GC (questions 1 à 5)

Questions et réponses d'entretien Java GC (questions 1 à 5)

Nov 16, 2019 pm 04:06 PM
java

Questions et réponses d'entretien Java GC (questions 1 à 5)

1. Puisqu'il existe un mécanisme GC, pourquoi y a-t-il encore des fuites de mémoire

Théoriquement, Java a un mécanisme de récupération de place (GC) ? ) Il n'y aura pas de problème de fuite de mémoire (c'est aussi une raison importante pour laquelle Java est largement utilisé dans la programmation côté serveur). Cependant, dans le développement réel, il peut y avoir des objets inutiles mais accessibles qui ne peuvent pas être recyclés par GC, provoquant ainsi des fuites de mémoire.

Par exemple, les objets de la session d'hibernate (cache de premier niveau) sont persistants et le garbage collector ne recyclera pas ces objets. Cependant, il peut y avoir des objets inutiles dans ces objets s'ils ne sont pas fermés. à temps (close ) ou vider le cache de premier niveau peut provoquer des fuites de mémoire.

Le code de l'exemple ci-dessous peut également provoquer une fuite de mémoire.

import java.util.Arrays;
import java.util.EmptyStackException;
public class MyStack<T> {
    private T[] elements;
    private int size = 0;
    private static final int INIT_CAPACITY = 16;
    public MyStack() {
        elements = (T[]) new Object[INIT_CAPACITY];
    }
    public void push(T elem) {
        ensureCapacity();
        elements[size++] = elem;
    }
    public T pop() {
        if (size == 0) throw new EmptyStackException();
        return elements[--size];
    }
    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements,2 * size + 1);
        }
    }
}
Copier après la connexion

Le code ci-dessus implémente une structure de pile (FILO) À première vue, il ne semble y avoir aucun problème évident. Il peut même réussir divers tests unitaires que vous écrivez.

Cependant, la méthode pop a un problème de fuite de mémoire. Lorsque nous utilisons la méthode pop pour faire apparaître un objet dans la pile, l'objet ne sera pas récupéré, même si le programme utilisant la pile ne les référence plus. objects , car la pile conserve des références obsolètes à ces objets. Dans les langages qui prennent en charge le garbage collection, les fuites de mémoire sont très cachées. Ce type de fuite de mémoire est en fait une rétention d'objet inconsciente.

Si une référence d'objet est conservée inconsciemment, le ramasse-miettes ne traitera pas cet objet, ni les autres objets référencés par cet objet, même s'il n'y a que quelques objets de ce type, il peut en résulter. de nombreux objets sont exclus du garbage collection, ce qui a un impact significatif sur les performances, dans des cas extrêmes, cela peut provoquer un Disk Paging (échange de données entre la mémoire physique et la mémoire virtuelle du disque dur), voire provoquer une OutOfMemoryError.

2. Pourquoi y a-t-il un mécanisme GC en Java ?

·Considérations de sécurité ; --pour la sécurité.

·Réduire les fuites de mémoire ; --effacer les fuites de mémoire dans une certaine mesure.

·Réduire la quantité de travail du programmeur. --Les programmeurs ne s'inquiètent pas de la libération de mémoire.

3. Quelle mémoire doit être recyclée pour le GC de Java ?

Lorsque la mémoire est en cours d'exécution, la JVM disposera d'une zone de données d'exécution pour gérer la mémoire.

Il comprend principalement 5 parties :

Program CounterRegister ;

Pile de machines virtuelles (VM Stack) ;

Pile de méthodes natives ; ;

Zone de méthode

Tas.

Le compteur de programme, la pile de machine virtuelle et la pile de méthodes locales sont les espaces mémoire privés de chaque thread. Ils naissent et meurent avec le thread. Par exemple, la quantité de mémoire allouée dans chaque cadre de pile de la pile est fondamentalement connue lorsque la structure de classe est déterminée. Par conséquent, l'allocation de mémoire et le recyclage de ces trois zones sont déterminés, et il n'est pas nécessaire de considérer la question de la mémoire. recyclage.

Mais la zone de méthode et le tas sont différents. Plusieurs classes d'implémentation d'une interface peuvent nécessiter une mémoire différente. Nous ne saurons quels objets seront créés lors de l'exécution du programme. de mémoire Ils sont tous dynamiques, et le GC se concentre principalement sur cette partie de la mémoire. Dans l’ensemble, la mémoire récupérée principalement par GC est la zone de méthode et le tas de la JVM.

4. Quand le GC de Java collecte-t-il les déchets ?

Je rencontre souvent cette question dans les interviews (en fait, je l'ai aussi rencontrée) : Comment juger qu'un objet est mort ?

Une réponse simple à laquelle penser est : ajouter un compteur de référence à un objet. Chaque fois qu'il y a une référence à celui-ci, la valeur du compteur est incrémentée de 1 ; lorsque la référence expire, la valeur du compteur est décrémentée de 1. Lorsque la valeur du compteur est 0, l'objet ne sera plus utilisé et est jugé mort. N'est-ce pas simple et intuitif ?

Cependant, c'est dommage. Cette approche est fausse ! Pourquoi est-ce faux ? En fait, utiliser le comptage de références est effectivement une bonne solution dans la plupart des cas, et il existe de nombreux cas dans les applications réelles, mais cela ne peut pas résoudre le problème des références circulaires entre objets.

Par exemple, il y a un champ dans l'objet A qui pointe vers l'objet B, et il y a un champ dans l'objet B qui pointe vers l'objet A. En fait, les deux ne sont plus utilisés, mais la valeur du compteur ne peut jamais être 0. , il ne sera pas recyclé, et alors une fuite mémoire se produit.

Quelle devrait être la bonne approche ?

Dans des langages tels que Java et C#, la méthode la plus courante pour déterminer la mort d'un objet est : l'analyse d'accessibilité. Tous les objets générés sont appelés « racines GC » « le sous-arbre de la racine. .

Recherche vers le bas à partir des Racines GC. Le chemin parcouru par la recherche est appelé chaîne de référence. Lorsqu'un objet n'a pas de chaîne de référence pour atteindre les Racines GC, on dit que l'objet est inaccessible (non-accessible). référençable), c'est-à-dire qu'il peut être recyclé par GC.

Qu'il s'agisse d'un compteur de références ou d'une analyse d'accessibilité, déterminer si un objet est vivant est lié aux références ! Alors, comment définir une référence à un objet ?

我们希望给出这样一类描述:当内存空间还够时,能够保存在内存中;如果进行了垃圾回收之后内存空间仍旧非常紧张,则可以抛弃这些对象。所以根据不同的需求,给出如下四种引用,根据引用类型的不同,GC回收时也会有不同的操作:

强引用(Strong Reference):Object obj=new Object();只要强引用还存在,GC永远不会回收掉被引用的对象。

软引用(Soft Reference):描述一些还有用但非必需的对象。在系统将会发生内存溢出之前,会把这些对象列入回收范围进行二次回收(即系统将会发生内存溢出了,才会对他们进行回收)

弱引用(Weak Reference):程度比软引用还要弱一些。这些对象只能生存到下次GC之前。当GC工作时,无论内存是否足够都会将其回收(即只要进行GC,就会对他们进行回收。)

虚引用(Phantom Reference):一个对象是否存在虚引用,完全不会对其生存时间构成影响。关于方法区中需要回收的是一些废弃的常量和无用的类。

1.废弃的常量的回收。这里看引用计数就可以了。没有对象引用该常量就可以放心的回收了。

2.无用的类的回收。什么是无用的类呢?

A.该类所有的实例都已经被回收。也就是Java堆中不存在该类的任何实例;

B加载该类的ClassLoader已经被回收;

C.该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

总而言之:对于堆中的对象,主要用可达性分析判断一个对象是否还存在引用,如果该对象没有任何引用就应该被回收。而根据我们实际对引用的不同需求,又分成了4种引用,每种引用的回收机制也是不同的。

对于方法区中的常量和类,当一个常量没有任何对象引用它,它就可以被回收了。而对于类,如果可以判定它为无用类,就可以被回收了。

5、通过10个示例来初步认识Java8中的lambda表达式

用lambda表达式实现Runnable

// Java 8 之前:
new Thread(new Runnable(){
    @Override
    public void run(){
        System.out.println("Before Java8, too much code for too little to do");
    }}).start();
    //Java 8 方式:
    new Thread(()->System.out.println("In Java8, Lambda expression rocks !!")).start();
Copier après la connexion

输出:

too much code,for too little to do
Lambda expression rocks!!
Copier après la connexion

这个例子向我们展示了Java 8 lambda表达式的语法。你可以使用lambda写出如下代码:

(params) -> expression (params) -> statement
(params) -> { statements }
Copier après la connexion

例如,如果你的方法不对参数进行修改、重写,只是在控制台打印点东西的话,那么可以这样写:

() -> System.out.println("Hello Lambda Expressions");
Copier après la connexion

如果你的方法接收两个参数,那么可以写成如下这样:

(int even, int odd) -> even + odd
Copier après la connexion

顺便提一句,通常都会把lambda表达式内部变量的名字起得短一些。这样能使代码更简短,放在同一行。所以,在上述代码中,变量名选用a、b或者x、y会比even、odd要好。

使用Java 8 lambda表达式进行事件处理

如果你用过Swing API编程,你就会记得怎样写事件监听代码。这又是一个旧版本简单匿名类的经典用例,但现在可以不这样了。你可以用lambda表达式写出更好的事件监听代码,如下所示:

// Java 8 之前:
JButton show = new JButton("Show"); show.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Event handling without lambda expression is boring");
    }
});
// Java 8 方式:
show.addActionListener((e) -> {
    System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
});
Copier après la connexion

使用Java 8 lambda表达式进行事件处理 使用lambda表达式对列表进行迭代

如果你使过几年Java,你就知道针对集合类,最常见的操作就是进行迭代,并将业务逻辑应用于各个元素,例如处理订单、交易和事件的列表。

由于Java是命令式语言,Java 8之前的所有循环代码都是顺序的,即可以对其元素进行并行化处理。如果你想做并行过滤,就需要自己写代码,这并不是那么容易。

通过引入lambda表达式和默认方法,将做什么和怎么做的问题分开了,这意味着Java集合现在知道怎样做迭代,并可以在API层面对集合元素进行并行处理。

下面的例子里,我将介绍如何在使用lambda或不使用lambda表达式的情况下迭代列表。你可以看到列表现在有了一个forEach()方法,它可以迭代所有对象,并将你的lambda代码应用在其中。

// Java 8 之前:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API","Date and Time API");
for (String feature : features) {
    System.out.println(feature);
}
// Java 8 之后:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API","Date and Time API");
features.forEach(n -> System.out.println(n));
// 使用 Java 8 的方法引用更方便,方法引用由::双冒号操作符标示,
// 看起来像 C++的作用域解析运算符
features.forEach(System.out::println);
Copier après la connexion

输出:

Lambdas Default Method Stream API
Date and Time API
Copier après la connexion

列表循环的最后一个例子展示了如何在Java 8中使用方法引用(method reference)。你可以看到C++里面的双冒号、范围解析操作符现在在Java 8中用来表示方法引用。

使用lambda表达式和函数式接口Predicate

除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做java.util.function。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用java.util.function.Predicate函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。下面是Java 8 Predicate的例子,展示了过滤集合数据的多种常用方法。Predicate接口非常适用于做过滤。

public static void main(String[]args){
    List languages=Arrays.asList("Java", "Scala","C++", "Haskell", "Lisp");
    System.out.println("Languages which starts with J :");
    filter(languages, (str)->str.startsWith("J"));
    System.out.println("Languages which ends with a ");
    filter(languages, (str)->str.endsWith("a"));
    System.out.println("Print all languages :");
    filter(languages, (str)->true);
    System.out.println("Print no language : ");
    filter(languages, (str)->false);
    System.out.println("Print language whose length greater than 4:");
    filter(languages, (str)->str.length()>4);
}
public static void filter(List names, Predicate condition){
    for(String name:names){
        if(condition.test(name)){
            System.out.println(name+" ");
        }
    }
}
// filter 更好的办法--filter 方法改进
public static void filter(List names, Predicate condition) {
    names.stream().filter((name)->(condition.test(name))).forEach((name)->
{System.out.println(name + " ");
    });
}
Copier après la connexion

可以看到,Stream API的过滤方法也接受一个Predicate,这意味着可以将我们定制的filter()方法替换成写在里面的内联代码,这就是lambda表达式的魔力。另外,Predicate接口也允许进行多重条件的测试。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Générateur de nombres aléatoires en Java Générateur de nombres aléatoires en Java Aug 30, 2024 pm 04:27 PM

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Horodatage à ce jour en Java Horodatage à ce jour en Java Aug 30, 2024 pm 04:28 PM

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Programme Java pour trouver le volume de la capsule Programme Java pour trouver le volume de la capsule Feb 07, 2025 am 11:37 AM

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

See all articles