1 java内存结构概述

java内存结构图如下

Java代码执行时内存状况 java程序运行内存图_Java代码执行时内存状况

class文件->运行时数据区->jni
运行时数据区
栈区
    虚拟机栈
        特征:线程私有,生命周期与线程相同,使用连续的内存空间
        作用:Java 方法执行的内存模型,存储局部变量表、操作栈、动态链接、方法出口等信息
    本地方法栈

    程序计数器
        特征:占用内存小,线程私有,生命周期与线程相同
        作用:大致为字节码行号指示器
方法区
    特征:线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址,是一个概念,不同的java版本有不同的实现,如永久代和元空间
    作用:存储运行时常量池+静态变量+常量+字段+方法字节码+在类/实例/接口初始化用到的特殊方法等
堆区
    新生代
        伊甸区
        from区
        to区
    老年代
    永久代(java7及之前)
        方法区的实现,逻辑上属于堆,实际上属于堆外内存,使用的是jvm内存
    元空间(java8及之后)
        方法区的实现,逻辑上属于堆,实际上属于堆外内存。元空间并不在虚拟机中,而是使用本地内存

 

2 案例分析

2.1 对象、属性内存分析

// 学生类:

public class Student {

    //静态的数据

    String name;

    int id;    //学号

    int age;

    String gender;

    int weight;

    Computer computer;



    //动态的行为

    public void study(){

        System.out.println(name+"在學習");

    }

 

    public void sayHello(String sname){

        System.out.println(name+"向"+sname+"說:你好!");

    }

}

 

// 电脑类:

public class Computer {

    String brand;

    int cpuSpeed;

}

 

主程序:

Student s1 = new Student();

s1.name = "高琪";

s1.age = 18;



Computer c = new Computer();

c.brand = "联想";

c.cpuSpeed = 100;

s1.computer = c;

内存分析:

Java代码执行时内存状况 java程序运行内存图_System_02

 

2.2 多态内存分析

多态构成的三个条件:继承、重写父类非静态方法、父类指针指向子类对象。

class HttpServlet{

    public void service(){

        doGet();

    }



    public void doGet(){

        System.out.println("HttpServlet.doGet");

    }



    public static void getInstance(){

        System.out.println("获取HttpServlet实例");

    }



    public static void init(){

        System.out.println("初始化配置");

    }



}



class MyHttpServlet extends HttpServlet{



    @Override

    public void doGet() {

        System.out.println("MyHttpServlet.doGet");

    }



    public void doPost(){

        System.out.println("MyHttpServlet.doPost");

    }



    public static void getInstance(){

        System.out.println("获取MyHttpServlet实例");

    }

}

 

说明:

每个方法都有两个隐式参数,this、supper。this指向创建的对象,supper指向父类对象。由于编译器问题,父类指针引用子类对象,调用方法的时候只能调用父类中存在的方法;如果子类有覆盖,则调用覆盖后的方法。

测试代码:

 

HttpServlet servlet1 = new HttpServlet();

servlet1.service();//HttpServlet.doGet



HttpServlet servlet2 = new MyHttpServlet();

servlet2.service();//MyHttpServlet.doGet

//servlet2.doPost();//报错

静态方法是属于某一个类的,子类不能重写父类的静态方法,子类与父类静态方法相同的时候不能构成重写,两个方法没有任何关系,如果子类方法加Override注解则报错。但是子类能继承父类的静态方法。调用的时候不传递this、supper隐式参数。

测试代码:

HttpServlet.getInstance();//获取HttpServlet实例

MyHttpServlet.getInstance();//获取MyHttpServlet实例

//子类调用父类的静态方法

MyHttpServlet.init();//初始化配置