堆、栈、方法区、常量池面试遇到怎么答?

结构化语言里函数(子程序)调用最方便的实现方式就是用栈,以至于现在绝大部分芯片都对栈提供芯片级的硬件支持,一条指令即可搞定栈的pop操作。

栈的好处是:方便、快、有效避免内存碎片化。栈的问题是:不利于管理大内存(尤其在16位和32位时代)、数据的生命周期难于控制(栈内的有效数据通常是连续存储的,所以pop时后申请的内存必须早于先申请的内存失效),所以栈不利于动态地管理并且有效地利用宝贵的内存资源。于是有了堆

JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)也叫静态存储区。

堆区:

1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身

栈区:

1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中 
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

方法区:

1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。 

2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

堆和栈的区别可以用如下的比喻来看出:

  • 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就 
    走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自 
    由度小。

  • 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由 
    度大。

      方法区: 用于储存已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
       垃圾收集行为在方法区很少出现,这块区域回收的主要目标是针对常量池的回收和对类型的卸载            
      运行时常量池:
                  方法区的一部分
                 常量池用于存放编译期生成的各种字面量和符号引用(还有翻译出来的直接引用),这部分内容在类加载后进入方法              区的运行时常量池中存放。 

                 运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,运行期间也可能将新的常量放入池中

       String str = "abc"创建对象的过程
        1 首先在常量池中查找是否存在内容为"abc"字符串对象
        2 如果不存在则在常量池中创建"abc",并让str引用该对象

        3 如果存在则直接让str引用该对象

         

        (2)String str = new String("abc")创建实例的过程
        1 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
        2 在字符串常量池中查看,是否存在内容为"abc"字符串对象
        3 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
        4 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来

            String str1 = "abc"; String str2 = "ab" + "c"; str1==str2是ture
            是因为String str2 = "ab" + "c"会查找常量池中时候存在内容为"abc"字符串对象,如存在则直接让str2引用该对象,显然String str1 = "abc"的            时候,上面说了,会在常量池中创建"abc"对象,所以str1引用该对象,str2也引用该对象,所以str1==str2
            String str1 = "abc"; String str2 = "ab"; String str3 = str2 + "c"; str1==str3是false                ---------//可参考Java编程思想第四版P284,285

            是因为String str3 = str2 + "c"涉及到变量(不全是常量)的相加,所以会生成新的对象,其内部实现是先new一个StringBuilder,然后 appe            nd(str2),append("c");然后让str3引用toString()返回的对象

             问:String s = new String(“abc”); 产生几个对象?

             答:一个或两个,如果常量池中原来没有 ”abc”, 就是两个(参考栈中的数据共享)。

             本文参考链接:https://blog.csdn.net/fuckluy/article/details/50614983

                                      https://blog.csdn.net/tobetheender/article/details/53258258

猜你喜欢

转载自blog.csdn.net/weixin_30363263/article/details/80268723