• 0

  • 0

Java学习日记(四)-内存管理 & 值传递和引用传递 & GC

1 month ago

内存管理 & 值传递和引用传递 & GC

内存管理

  • Java程序所使用的内存是由Java虚拟机进行管理、分配的。

  • Java虚拟机对内存的管理:

1、Java虚拟机在内存中划分的区域:

  • 方法区(默认最大容量是64M)又划分出静态区、常量池
    • 静态区:存放静态变量、程序运行期间,类名首次出现的时候,静态变量就被分配内存了。
    • 常量池:存放字面量对象。字面量会增加不会改变。
  • 堆区(默认最大容量是256M):存放实例对象的属性、数组值;每new一次就在堆中分配一次内存
  • 栈区(虚拟机栈 默认最大容量是1M):先进后出;程序调用方法时会在栈中划分一块栈帧,栈帧中的内存供局部变量( 包括基本类型和局部类型)使用,方法调用结束后会收回此栈帧占用的内存

2、Java内存区域图:

  • 加载顺序:
    1. 当一个类的类名首次出现时,JVM将类的字节码(.class)加载到方法区中
    2. 为类的静态属性分配(静态区中的)内存
    3. 调用类的静态块,为静态属性初始化;静态块只在加载类后调用一次。
    4. 实例化对象时(在堆中)为对象的属性分配内存(如果没有实例化就不分配)
    5. 调用构造方法,为属性初始化
  • 运行顺序
    1. 程序从main()方法开始运行,JVM在栈中为方法开辟内存空间
    2. 方法名入栈后,栈帧指向该方法
    3. 为方法中的局部变量在栈中分配内存
    4. 调用下一个方法时,重复执行1~3步
    5. JVM释放某方法的内存空间时,该方法中的局部变量内存也被回收
  • main()最先执行,一般都在栈底,调用其他方法时,其他方法再往上压,那么,什么时候main()被回收?

5、变量的内存分配

  • 静态变量:静态区,与类同生死,类加载后就有初始值了;
  • 实例变量:堆中,与对象同生死,对象new出来后才有初始值;
  • 局部变量:栈中,使用前要先初始化,系统不管的。

值传递和引用传递

  • 基本数据类型采用值传递;如果方法的参数是基本数据类型,Java虚拟机会拷贝参数的值,访如新的栈帧

  • 引用数据类型采用引用传递;如果方法的参数是引用数据类型,Java虚拟机会拷贝引用对象在堆中的地址,放入新的栈帧中。

  • 引用传递是为了提高运行效率,减少内存浪费

  • 例子:

    class Student{
        String name;
        int age;
    }
    public class ValueTransform {
        public static void main(String[] args) {
            Student stu = new Student();
            stu.name = "思恩";
            stu.age = 18;
            changeInt(stu.age);
            System.out.println("调用changeInt(int)的结果是:" + stu.age);
            changeStudent(stu);
            System.out.println("调用changeStudent(Student)的结果是:" + stu.age);
        }
    
        public static void changeInt(int i) {
            i ++;
        }
        public static void changeStudent(Student stu1) {
            stu1.age ++;
        }
    }
    复制代码

    输出结果:

    调用changeInt(int)的结果是:18

    调用changeStudent(Student)的结果是:19

垃圾回收机制(gc)

  • 由Java虚拟机内部的垃圾回收线程自动对不再使用的内存进行回收,这种机制称为垃圾回收机制。
  • 回收顺序:
    • 虚引用 幽灵引用,存在感很弱很弱
    • 弱引用 回收机制来查两次还是弱就回收,内存近满也把它回收了
    • 软引用 还存在耦合
    • 强引用 基本不回收,比如new出来的东西

1、在堆、栈、方法区中的垃圾回收

  • 堆:主要回收不再被引用的对象数据所占用的内存
  • 栈:栈会在方法调用时划分栈帧,方法调用结束时回收栈帧,不需要垃圾回收
  • 方法区:回收不再被对象引用的结构所占用的内存

2、Runtime类的使用

返回类型 方法名称 作用
Runtime getRuntime 获取Runtime对象
long totalMemory() 获取JVM分配给程序的内存数量
Long freeMemory() 获取当前可用的内存数量
Long maxMemory() 获取Java虚拟机可以申请到的最大内存数量
void gc() 建议Java虚拟机进行垃圾回收
  • gc()方法只会建议Java虚拟机进行垃圾回收,但是不保证一定会进行
免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

java

0

Relevant articles

未登录头像

No more data