关于Java GC和我的堆栈实现链接列表

Posted

技术标签:

【中文标题】关于Java GC和我的堆栈实现链接列表【英文标题】:About Java GC and my stack implementation link list 【发布时间】:2020-12-11 10:36:44 【问题描述】:

一天前我决定开始学习 Java。我选择实现堆栈(链表实现)和其他数据结构来学习它,但我不太确定我的代码,以及 Java GC 的行为,你们能检查我的代码是对还是错吗?

很抱歉,我不认识任何 Java 专家来询问我是否做对了。

顺便说一句,我来自 C 和 C++,我对我的程序占用的内存非常满意。

我尝试运行这个程序并推送了 500mb 的内存,然后当我使用 .pop() 方法时内存没有下降,我也等了大约 20 分钟,但没有任何反应。 我读到的是 java 会自动为我们释放内存,但由于我没有看到它出现故障,所以感觉好像我做错了。

我的堆栈

import java.util.Scanner;

// ------------------------  node  ------------------------
class node<type>
    type value;
    node<type> prev;

    node(type value)
        this.value = value;
    

    // for checking I guess
    void recdisp(node<type> recurs)
        if(recurs != null)
            System.out.println(recurs.value);
            recurs.recdisp(recurs.prev);
        
        return;
    


// ------------------------  STACK  ------------------------
class mystack<type>
    node<type> top;

    mystack(type value)
        top = new node<type>(value);
        top.prev = null;
    

    void push(type value)
        node<type> buffer = new node<type>(value);
        buffer.prev = top;
        top = buffer;
        buffer = null;
    

    type pop()
        node<type> tmp;
        if(top == null)
            System.out.println("POP: Stack is Empty");
            return null;
        
        type pass = top.value;
        tmp = top;
        top = top.prev;
        tmp = null;
        return pass;
    

    void peek()
        System.out.println("TOP VALUE : "+top.value);
    

    void display()
        if(top != null)
            top.recdisp(top);
        else
            System.out.println("Display: Stack is empty");
    



//  ------------------------  MAIN CLASS  ------------------------
public class myjava
    public static void main(String []args)

        mystack<Integer> stacks = new mystack<Integer>(5);
        stacks.pop();
        stacks.pop();
        stacks.pop();
        stacks.display();

        stacks.push(10);
        stacks.push(20);
        stacks.push(30);
        stacks.push(40);

        stacks.display();
    

【问题讨论】:

您对内存“下降”的预期究竟如何? JVM 通常不会将分配的 RAM 返回给 OS,因为它猜测如果它需要 500MB 一次,它会再次需要它。 @chrylis -cautiouslyoptimistic 哦,我明白了,我在看我系统的内存,我以为我可以看到它下降了,但是我怎么能看到我的程序在 java 中的内存使用情况虚拟机?,我的代码也有问题吗? 【参考方案1】:

好的,我现在已经知道如何正确监控我的java程序的内存了,我使用“jconsole”应用程序来监控JVM中分配的堆内存,但似乎我需要点击这个“请求垃圾”在它可以从我的堆栈中释放 .poped() 内存之前,我现在正在寻找一种方法来在我的 java 程序中执行此“请求垃圾收集”。

【讨论】:

你根本不需要'请求垃圾收集',JVM会自己决定什么时候需要垃圾收集(例如当它需要分配,但空间不足时) .何时执行取决于 Java 版本、选择的垃圾收集器及其配置。 正如马克所说,这样做是为了了解内存消耗,但在实际应用中既没有必要也不推荐; JVM 知道何时执行垃圾回收。【参考方案2】:

这里涉及到几个概念。

JVM 为您的应用程序提供自动内存管理。与 C 不同,您不需要显式地为对象分配空间; JVM 将在堆中为您执行此操作。当您不再拥有对某个对象的任何引用时,它就有资格进行垃圾回收。重要的是要认识到,不能保证何时(或什至是否)收集对象。

大多数 GC 算法使用分代堆空间(将其分为年轻代和年老代)。您创建的几乎所有对象都只会在很短的时间内被引用。大部分对象都在年轻代收集,减少了老年代的负载。

直到最近,JVM 还不愿意将未使用的堆内存返回给操作系统。在 JDK 12 中,JEP 346 为 G1 收集器引入了即时内存释放。其他一些收藏家也做类似的事情,但不是全部。

根据您的问题,无法准确说出正在发生的事情。你没有说明你的堆有多大(或者你的机器有多少内存)。如果年轻代足够大,创建 500Mb 的数据甚至可能不会触发次要 GC 周期。此外,很大程度上取决于您使用的 JDK 版本。

【讨论】:

以上是关于关于Java GC和我的堆栈实现链接列表的主要内容,如果未能解决你的问题,请参考以下文章

关于Java泛型的使用

打怪升级jvm关于jvm内存模型及GC调优

在 python 中使用链表实现堆栈。 pop 方法的问题和关于可变性的问题

JVM对象A和B循环引用,最后会不会不被GC回收?-------关于Java的GC机制

关于JAVA堆栈的简单说明

关于我和我的的故事