zoukankan      html  css  js  c++  java
  • Jvm方法区以及static的内存分配图

    前面的几篇都没有太明确地指出 方法区 是什么?现在通过一些资料的收集和学习,下面做一些总结

    什么是方法区:

    方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息的(类的描述信息)。

    方法区存放的信息包括:

    类的基本信息:

    1.每个类的全限定名

    2.每个类的直接超类的全限定名(可约束类型转换)

    3.该类是类还是接口

    4.该类型的访问修饰符

    5.直接超接口的全限定名的有序列表

    已装载类的详细信息

    1.      运行时常量池:在方法区中,每个类型都对应一个常量池,存放该类型所用到的所有常量,常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。

    2.      字段信息:字段信息存放类中声明的每一个字段的信息,包括字段的名、类型、修饰符。

    3.      方法信息:类中声明的每一个方法的信息,包括方法名、返回值类型、参数类型、修饰符、异常、方法的字节码。

    (在编译的时候,就已经将方法的局部变量、操作数栈大小等确定并存放在字节码中,在装载的时候,随着类一起装入方法区。)

    4.      静态变量:类变量,类的所有实例都共享,我们只需知道,在方法区有个静态区,静态区专门存放静态变量和静态块。

    5.      到类classloader的引用:到该类的类装载器的引用。

    6.      到类class 的引用:虚拟机为每一个被装载的类型创建一个class实例,用来代表这个被装载的类。 

    下面分析static的内存分配

    1.  
      public class Dome_Static {
    2.  
       
    3.  
      public static void main(String[] args) {
    4.  
      Person p1 = new Person();
    5.  
      p1.name = "xiaoming";
    6.  
      p1.country = "chinese";
    7.  
      Person p2 = new Person();
    8.  
      p2.name = "xiaohong";
    9.  
      p1.speak();
    10.  
      p2.speak();
    11.  
      }
    12.  
       
    13.  
      }
    14.  
      class Person {
    15.  
      String name;
    16.  
      static String country;
    17.  
      public void speak() {
    18.  
      System.out.println("name:"+name+",country:"+country);
    19.  
      }
    20.  
      }
    1.  
      Output:
    2.  
      name:xiaoming,country:chinese
    3.  
      name:xiaohong,country:chinese
     
    `


    1.首先,先加载Dome_Static,然后其main函数入栈,之后Person被加载。static声明的变量会随着类的加载而加载,所以在内存中只会存在一份,实例化多个对象,都共享同一个static变量,会默认初始化

    2.在栈内存为 p1 变量申请一个空间,在堆内存为Person对象申请空间,初始化完毕后将其地址值返回给p1,通过p1.name和p1.country修改其值

    3.在栈内存为 p2 变量申请一个空间,在堆内存为Person对象申请空间,初始化完毕后将其地址值返回给p2,仅仅通过p2.name修改其值

    4.打印show方法,进栈,这里就不画图了,对于栈相关的概念不清楚的可以看看在之前发的博客。简单口述下:p1.show()  show方法入栈,在方法的内部有个指向堆内存的this引用,通过该引用可找到堆内存实体,打印country时,可通过该堆内存对象找到对应的类,读取对应静态区中的字段值

    最后给大家一道面试题练练手,要求写出其结果(笔试)

    1.  
      public class StaticTest {
    2.  
          
    3.  
          public static int k = 0;
    4.  
          public static StaticTest t1 = new StaticTest("t1");
    5.  
          public static StaticTest t2 = new StaticTest("t2");
    6.  
          public static int i = print("i");
    7.  
          public static int n = 99;
    8.  
          public int j = print("j");
    9.  
           
    10.  
          {
    11.  
              print("构造块");
    12.  
          }
    13.  
           
    14.  
          static{
    15.  
              print("静态块");
    16.  
          }
    17.  
           
    18.  
          public StaticTest(String str) {
    19.  
              System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
    20.  
              ++n;
    21.  
              ++i;
    22.  
          }
    23.  
           
    24.  
          public static int print(String str) {
    25.  
              System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
    26.  
              ++i;
    27.  
              return ++n;
    28.  
          }
    29.  
          public static void main(String[] args) {
    30.  
              StaticTest t = new StaticTest("init");
    31.  
          }
    32.  
       
    33.  
      }


    结果:

    1.  
      1:j i=0 n=0
    2.  
      2:构造块 i=1 n=1
    3.  
      3:t1 i=2 n=2
    4.  
      4:j i=3 n=3
    5.  
      5:构造块 i=4 n=4
    6.  
      6:t2 i=5 n=5
    7.  
      7:i i=6 n=6
    8.  
      8:静态块 i=7 n=99
    9.  
      9:j i=8 n=100
    10.  
      10:构造块 i=9 n=101
    11.  
      11:init i=10 n=102


    这个留给大家去思考,如果一眼便能便知道为什么是这样的输出结果,那么静态方面知识应该比较扎实了

    提示一下 :

    1.加载的顺序:先父类的static成员变量 -> 子类的static成员变量 -> 父类的成员变量 -> 父类构造 -> 子类成员变量 -> 子类构造

    2.static只会加载一次,所以通俗点讲第一次new的时候,所有的static都先会被全部载入(以后再有new都会忽略),进行默认初始化。在从上往下进行显示初始化。这里静态代码块和静态成员变量没有先后之分,谁在上,谁就先初始化

    3.构造代码块是什么?把所有构造方法中相同的内容抽取出来,定义到构造代码块中,将来在调用构造方法的时候,会去自动调用构造代码块。构造代码快优先于构造方法。

    转载自:https://blog.csdn.net/Wang_1997/article/details/52267688

  • 相关阅读:
    token是什么?和session什么区别,怎么用
    HashTable详解
    Cookie和Session的区别
    测试基础面试题
    什么是回归测试?回归测试的主要目的是什么?
    每天一个linux常用命令--ls 和 -ll 有什么区别?
    python中6个序列的内置类型分别是什么,列表和元组的异同有哪些
    今天去面试自动化测试,被几个问题问住了,记录下
    python排序算法-冒泡和快速排序,解答阿里面试题
    Myeclipse使用积累
  • 原文地址:https://www.cnblogs.com/lwthad/p/10253322.html
Copyright © 2011-2022 走看看