目录
学习路线
Program Counter Register 程序计数器(寄存器)
当一条指令执行时,会先送到解释器,解释器将指令转换为机器码,传递给CPU,然后程序计数器记录吓一跳指令的地址。
Java Virtual Machine Stacks (Java 虚拟机栈)
问题:
1. 垃圾回收是否涉及栈内存?
不涉及,因为在每次调用方法结束后,都会被弹出栈,会被自动的回收
2. 栈内存分配越大越好吗?
-xss给虚拟机划分内存,栈内存化的越大,反而会让线程数变少,因为物理内存是一定的,栈内存越大,线程数就变少了
3. 方法内的局部变量是否线程安全?
如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
Heap 堆
特点
面试题;
- String s1 = "a";
- String s2 = "b";
- String s3 = "a" + "b";//"ab"
- String s4 = s1 + s2;//new String("ab")
- String s5 = "ab";
- String s6 = s4.intern();
- // 问
- System.out.println(s3 == s4);//false
- System.out.println(s3 == s5);//true
- System.out.println(s3 == s6);//true
- String x2 = new String("c") + new String("d");//new String ("cd")
- String x1 = "cd";
- x2.intern();
- // 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢
- System.out.println(x1 == x2);//false 因为常量池中已经有了"cd"所以x2.intern(); 不会将x2放入常量池
-
-
-
- ???J跟换[最后]两行代码
- String x2 = new String("c") + new String("d");//new String ("cd")
- x2.intern();
- String x1 = "cd";
- System.out.println(x1 == x2);//true 因为x2.intern()时,常量池没有"cd"所以放入了常量池
-
- ???如果在JDK1.6版本中呢
- String x2 = new String("c") + new String("d");//new String ("cd")
- x2.intern();
- String x1 = "cd";
- System.out.println(x1 == x2);//false 因为1.6中只会讲副本放入进去
先看下面的这个代码
- public class demo01 {
- public static void main(String[] args) {
- String s1 = "a";
- String s2 = "b";
- String s3 = "ab";
- }
- }
我们来分析一下这个代码
使用jclasslib插件工具,查看字节码
在编译下面的代码、
- public class demo01 {
- public static void main(String[] args) {
- String s1 = "a";
- String s2 = "b";
- String s3 = "ab";
- String s4 = s1 + s2;
- System.out.println(s3 == s4);
- }
- }
查看了字节码的流程以后我们可以知道,实际上S4的创建经历了
new StringBuilder.append("a").append("b").toString()
我们再来查看一下StringBuilder的toString()方法
- public final class StringBuilder
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
-
- @Override
- public String toString() {
- // Create a copy, don't share the array
- return new String(value, 0, count);
- }
- }
tostring()方法里面创建了一个新的对像,所以我们可以确定s3不等于s4;
创建出来的s3="ab"是存在与常量池中的,而s4则是存在于栈内存中
我们再来查看下面的代码,判断s3==s5
- public class demo01 {
- public static void main(String[] args) {
- String s1 = "a";
- String s2 = "b";
- String s3 = "ab";
- String s4 = s1 + s2;
- System.out.println(s3 == s4);
- String s5 = "a" + "b";
- System.out.println(s3 == s5);
- }
- }
System.out.println(s3 == s5); //true
池中的对象返回
JDK1.8特性
- public class demo01 {
- public static void main(String[] args) {
- String x = "ab";
- String s1 = new String ("a") + new String ("b");
- String s2 = s1.intern();
- System.out.println(x == s2); //true
- System.out.println(x == s1); //false
- }
- }
JDK1.6特性
在JDk1.6和JDK1.8时所处的位置
当内存空间不足时,长时间没引用的字符串常量会被回收
StringTable的底层是哈希表