java study notes "two"

Java memory allocation mainly includes the following areas:

1. Registers: we have no control in the program

2. Stack: continuous, first in last out. Stores basic types of data and references to objects, but the objects themselves are not stored on the stack, but on the heap.

3. Heap: Stores the data generated by new, not continuous.

4. Static fields: static members stored in objects defined with static

5. Constant pool: store constants (there is a sharing mechanism)

    Both the static area and the constant pool are located in the method area, and the method area also belongs to the heap area.

6. Non-RAM (Random Access Memory) storage: permanent storage space such as hard disks

*****************************************************************

Stack in Java Memory Allocation

  Some basic types of variable data and object reference variables defined in the function are allocated in the function's stack memory. When a variable is defined in a code block, Java allocates memory space for the variable in the stack. When the variable exits the scope, Java automatically releases the memory space allocated for the variable, which can be immediately used for other purposes. 

Heap in Java memory allocation

  Heap memory is used to store objects and arrays created by new . Memory allocated in the heap is managed by the Java Virtual Machine's automatic garbage collector.

   After an array or object is generated in the heap, a special variable can also be defined in the stack, so that the value of the variable in the stack is equal to the first address of the array or object in the heap memory, and the variable in the stack becomes Array or object reference variable. A reference variable is equivalent to a name for an array or object, and you can use the reference variable in the stack to access the array or object in the heap later in the program. A reference variable is like a name for an array or object.

  Reference variables are ordinary variables that are allocated on the stack when they are defined, and are released when the program runs out of scope. Arrays and objects themselves are allocated in the heap. Even if the program runs outside the code block where the statement that uses new to generate arrays or objects is located, the memory occupied by the arrays and objects themselves will not be released, and the arrays and objects have no reference variables to point to it. When it becomes garbage, it cannot be used, but it still occupies memory space and is collected (released) by the garbage collector at an indeterminate time. This is also the reason why Java occupies more memory. 

  In fact, variables on the stack point to variables in heap memory, which are pointers in Java! 

constant pool

  The constant pool refers to some data that is determined at compile time and stored in the compiled .class file. In addition to the constant values ​​(final) that contain various basic types (such as int, long , etc.) and object types (such as String and array ) defined in the code, it also contains some symbolic references in text form, such as: 

  1. Fully qualified names of classes and interfaces;
  2. field names and descriptors; 
  3. Methods and names and descriptors.

  The virtual machine must maintain a constant pool for each loaded type. The constant pool is an ordered set of constants used by the type, including direct constants (string, integer and floating point constants) and symbolic references to other types, fields and methods.

  For String constants, its value is in the constant pool. The constant pool in the JVM exists in the form of a table in the memory. For the String type, there is a fixed-length CONSTANT_String_info table used to store literal string values. Note: this table only stores literal string values, not symbols. Quote. Having said that, there should be a clearer understanding of the storage location of string values ​​in the constant pool.

  When the program is executed, the constant pool will be stored in the Method Area, not the heap.

heap and stack

  Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、 anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的堆的优势是可以动态地分配内存大小生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态 分配内存,存取速度较慢。 

  栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。

******************************************************************

 

  这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。

字符串内存分配:

  对于字符串,其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。 

如以下代码:


        String s1 = "china";
        String s2 = "china";
        String s3 = "china";

        String ss1 = new String("china");
        String ss2 = new String("china");
        String ss3 = new String("china");

  这里解释一下黄色这3个箭头,对于通过new产生一个字符串(假设为“china”)时,会先去常量池中查找是否已经有了“china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象。

  这也就是有道面试题:Strings=newString(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。

  存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的 intern()方法就是扩充常量池的 一个方法;当一个String实例str调用intern()方法时,Java 查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用

如下代码:


        String s0= "kvill";   
        String s1=new String("kvill");   
        String s2=new String("kvill");   
        System.out.println( s0==s1 );     
        s1.intern();   
        s2=s2.intern(); //把常量池中"kvill"的引用赋给s2   
        System.out.println( s0==s1);   
        System.out.println( s0==s1.intern() );   
        System.out.println( s0==s2 ); 

输出结果:

false
false
true
true

String常量池问题的几个例子:


【1】
String a = "ab"; String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = false 【2】
String a
= "ab"; final String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = true 【3】
String a
= "ab"; final String bb = getBB(); String b = "a" + bb; System.out.println((a == b)); //result = false private static String getBB() { return "b"; }

分析:

  【1】中,JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。

  【2】和【1】中唯一不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。

  【3】JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面程序的结果为false。

结论:

  字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。

基础类型的变量和常量在内存中的分配

  对于基础类型的变量和常量,变量和引用存储在栈中,常量存储在常量池中。

如以下代码:


        int i1 = 9;
        int i2 = 9;
        int i3 = 9;

        final int INT1 = 9;
        final int INT2 = 9;
        final int INT3 = 9;

  编译器先处理int i1 = 9;首先它会在栈中创建一个变量为i1的引用,然后查找栈中是否有9这个值,如果没找到,就将9存放进来,然后将i1指向9。接着处理int i2 = 9;在创建完i2的引用变量后,因为在栈中已经有9这个值,便将i2直接指向9。这样,就出现了i1与i2同时均指向9的情况。最后i3也指向这个9。

成员变量和局部变量在内存中的分配

  对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。   如以下代码:

class BirthDate {
    private int day;
    private int month;
    private int year;

    public BirthDate(int d, int m, int y) {
        day = d;
        month = m;
        year = y;
    }
    // 省略get,set方法………
}

public class Test {
    public static void main(String args[]) {
        int date = 9;
        Test test = new Test();
        test.change(date);
        BirthDate d1 = new BirthDate(7, 7, 1970);
    }

    public void change(int i) {
        i = 1234;
    }
}

  对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:    

  1. main方法开始执行:int date = 9; date局部变量,基础类型,引用和值都存在栈中。
  2. Test test = new Test();test为对象引用,存在栈中,对象(new Test())存在堆中。 
  3. test.change(date);  i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。
  4. BirthDate d1= new BirthDate(7,7,1970); d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。 
  5. main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(), new BirthDate()将等待垃圾回收。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325545419&siteId=291194637