Java-JVM内存

发布于:2022-12-06 ⋅ 阅读:(190) ⋅ 点赞:(0)

JAVA虚拟机内存模型概念

 内存模型

 Java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area.

虚拟机栈(简称:栈)的特点如下:

① 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

栈属于线程私有,不能实现线程间的共享!

栈的存储特性是"先进后出,后进先出"

栈是由系统自动分配,速度快!栈是一个连续的内存空间!

堆的特点如下:

堆用于存储创建好的对象和数组(数组也是对象)

JVM只有一个堆,被所有线程共享

堆是一个不连续的内存空间,分配灵活,速度慢!

堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。

方法区(也是堆)的特点如下:

 ① 方法区是JAVA虚拟机规范,可以有不同的实现

        i.JDK7以前是"永久代"

        ii.JDK7部分去除"永久代",静态变量、字符串常量池都挪到了堆内存中

        iii.JDK8是"元数据空间"和堆结合起来

② JVM只有一个方法区,被所有线程共享!

③ 方法区实际也是堆,只是用于存储类、常量相关的信息!

④ 用来存放程序永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

⑤ 常量池主要存放常量:如文本字符串、final常量值

程序执行过程内存分析

eg.编写Person类并分析内存

Public class Person{
    String name;
    int age;
    
public void show(){
    System.out.println(name);
}

public static void main(String[] args){
    //创建对象
    Person p1 = new Person();
    p1.age = 24;
    p1.name = "张三";
    p1.show();
    //创建p2对象
    Person p2 = new Person();
    p2.age = 35;
    p2.name = "李四";
    p2.show();
Person p3 = p1;
Person p4 = p1;
p4.age = 80;
System.out.println(p1.age);

    }
}

     

参数传值机制

 原身份证与复印件

Java中,方法中所有参数都是"值传递",也就是"传递的是值的副本"。也就是,我们得到的是"原参数的复印件,而不是原件"。

● 基本数据类型参数的传值

传递的是值的副本。副本改变不会影响原件

● 引用类型参数的传值

传递的是值的副本。但是引用类型指的是"对象的地址"。因此,副本和原参数都指向了同一个"地址",改变"副本指向地址对象的值,也意味着原参数指向对象的值也发生了改变"。

eg.多个变量指向同一个对象

public classs User{
    int id;  //id
    String name;  //账户名
    String pwd;   //密码


public User(int id,String name){
    this.id = id;
    this.name = name;
}

public static void main(String[] args){
    User u1 = new User(100,"高小七");
    User u3 = u1;
    System.out.println(u1.name);
    u3.name = "张三";
    System.out.println(u1.name);
    }
}

执行结果:

垃圾回收机制 (Garbage Collection)

Java引入了垃圾回收机制,令C++程序员最头疼的内存管理问题迎刃而解。Java程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大提高了开发效率。

垃圾回收原理和算法 

● 内存管理

Java的内存管理很大程度就是:堆中对象的管理,其中包括对象空间的分配和释放。

        ● 对象空间的分配:使用new关键字创建对象即可

        ● 对象空间的释放:将对象赋值null即可

● 垃圾回收的过程

任何一种垃圾回收算法一般都要做两件基本事情:

① 发现无用的对象

② 回收无用对象占用的内存空间

垃圾回收机制保证可以将"无用的对象"进行回收

无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清楚和整理。

● 垃圾回收相关算法

① 引用计数法

 堆中的每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为null),引用计数器减1,最后如果该对象的引用计算器的值为0时,则Java垃圾回收器会认为该对象是无用对象并对其进行回收。优点是算法简答,缺点是"循环引用的无用对象"无法识别。

eg.循环引用演示

代码中,s1和s2互相引用对方,导致他们引用计数不为0,但实际已经无用,但无法被识别

public class Student{
    String name;
    Student friend;
    

public static void main(String[] args){
    Student s1 = new Student();
    Student s2 = new Student();

s1.friend  = s2;
s2.friend  = s1;
s1 = null;
s2 = null;
    }
}

 ② 引用可达法(根据索算法)

程序把所有的引用关系看作一张图,从一个节点GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,及无用的节点。