【问题标题】:About Java GC and my stack implementation link list关于Java GC和我的堆栈实现链接列表
【发布时间】: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 中的内存使用情况虚拟机?,我的代码也有问题吗?

标签: java memory-management garbage-collection stack singly-linked-list


【解决方案1】:

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

【讨论】:

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

这里涉及到几个概念。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-15
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 2016-08-14
    • 2011-07-29
    相关资源
    最近更新 更多