Because java garbage collection mechanism, so tend not to pay attention to the stack heap memory allocation until OOM
First, understand the concept of a stack heap
1, create an instance of the storage heap [objects]
- The program starts running, JVM get some memory from OS, is part of heap memory. Heap memory typically underlying the storage addresses arranged upward.
- Stack is a "run-time" data field, the class is instantiated objects allocated from the heap up space;
- Space is allocated on the heap by "new" and other instructions establishment, the heap is dynamically allocated memory size, survival do not have to tell the compiler in advance;
- Unlike C ++ is, Java automatically manage the stack and heap, the garbage collector can automatically reclaim unused memory heap;
- The disadvantage is that, due to the dynamic allocation of memory at run-time, so the memory access slower.
2, stack [storage] basic types and reference types
- Last-out data structure, usually in a method for storing parameters, local variables;
- In java, all basic types (short, int, long, byte, float, double, boolean, char), and reference type of variables are stored in the stack;
- Living space in the stack data in the current generally Scopes ({...} by the enclosed region;
- Stack access speed faster than the reactor, located directly behind the CPU registers;
- Data can be shared stack, a plurality of reference can point to the same address;
- The downside is that the data on the stack size and survival must be determined, lack of flexibility.
3, summary
- Java heap memory allocated to the operating system is part of the JVM memory.
- When we create objects that are stored in the Java heap memory.
- You can adjust the size of the Java heap space by using JVM command-line options -Xms, -Xmx, -Xmn.
- The basic types of data stored in the stack: short, int, long, byte, float, double, boolean, char
- Just create new objects in the form of, then stored in a java heap memory.
Second, the data stored in the stack
1, the basic types of data storage
int a = 3;
int b = 3;
编译器先处理int a = 3;
首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,
然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。
这样,就出现了a与b同时均指向3的情况。
所以 a == b true
2、包装类数据存储
如Integer, Double, String等将相应的基本数据类型包装起来的类。
这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
以String为例
String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建。
前者是规范的类的创建过程,即在Java中,一切都是对象,而对象是类的实例,全部通过new()的形式来创建。
那为什么在String str = "abc";中,并没有通过new()来创建实例,是不是违反了上述原则?其实没有。
关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
- a、先定义一个名为str的对String类的对象引用变量:String str;
- b、在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象O,并将O的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象O。如果已经有了值为"abc"的地址,则查找对象O,并返回O的地址。
- c、将str指向对象O的地址。
值得注意的是,通常String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用(即:String str = "abc";既有栈存储,又有堆存储)。
为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
只有在两个引用都指向了同一个对象时才返回真值。str1与str2是否都指向了同一个对象)
结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。
3、总结
(1). 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。
担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向 String类的引用被创建了。
至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。
因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。
清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。
(2). 使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。
而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
(3). 由于String类的immutable性质(因为包装类的值不可修改),当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。
4、实例
String s = new String("abc") 创建了几个对象?
首先我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变量。
答案2个。
5、知识点
我们可以用==判断一下两个引用变量是否指向了一个地址即一个对象