设为首页 - 加入收藏 长治站长网 (http://www.0355zz.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 图片 平台 芯片
当前位置: 首页 > 综合聚焦 > 资源网站 > 空间 > 正文

JVM内存分配及String常用方法

发布时间:2019-09-04 20:23 所属栏目:[空间] 来源:奋进的小样
导读:一,JVM内存分配和常量池 在介绍String类之前,先来简单分析一下在JVM中,对内存的使用是如何进行分配的。如下图所示(注意:在jdk1.8之后便没有方法区了): 如上JVM将内存分为多个不同的区域,这些区域都有各自的用途、创建和销毁的时间,有些区域随虚拟机

JVM内存分配及String常用方法

?一,JVM内存分配和常量池

? 在介绍String类之前,先来简单分析一下在JVM中,对内存的使用是如何进行分配的。如下图所示(注意:在jdk1.8之后便没有方法区了):

JVM内存分配及String常用方法

? 如上JVM将内存分为多个不同的区域,这些区域都有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。

? 区域名称的说明:

1.1,方法区:

? 属于数据共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

1.2,虚拟机栈

? 虚拟机栈就是我们通常说的栈,是Java执行方法的内存模型,每当执行一次方法时,都会创建一个栈帧。把栈帧压入栈,当Java方法调用时返回正常的结果或者捕获异常时,栈帧出栈。

? 栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接。

1.3,本地方法栈

? 从功能上来说与虚拟机栈类似,但是虚拟机栈执行的是字节码,而本地方法栈调用的是Native方法,并且它是线程独享的。

1.4,程序计数器

? 程序计数器是线程独享的,它是记录当前线程执行的字节码行号。在多线程执行时,CPU会来回在线程之间进行切换,那么当再次回到一条线程时,是如何得知线程的存储单元及执行指令。而程序计数器便会进行存储下一条存储单元的地址,执行完毕后程序计数器自动加 1 ,以此循环直到程序结束为止。

1.5,堆

? 说到堆这个概念想必都不陌生,它是内存中的重要角色。它主要是用来存储被创建出来的对象,通过关键字new实例出来的,是所有线程共享的一块最大的区域。

? ==特别注意:在JDK1.7及以后,常量池移动到堆内存中。==

? 堆还包括一个==常量池==,用来存储编译期间生成的==字面量和符号==引用。这部分内容在类被加载后,都会存储到方法区中。同时,运行时产生的新常量也可以被放入常量池中,比如 String 类中的 intern() 方法产生的常量。

? 常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。

二,常量池

2.1,什么是常量:

? 常量是指被final修饰的变量,值一旦确定就无法改变。

? final可以修饰静态变量、方法、实例变量和局部变量。

? 常量池分为两种形式:静态常量池和运行时常量池

2.2,静态常量池

? 即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。这种常量池用于存放字面量和符号引用量。

2.3,运行时常量池

? 指JVM虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。同样运行时常量池一个重要的特征就是具有动态性,指并不需要常量只有在编译期才会产生,在运行期也会将新的常量保存到常量池中,如String类中的intern()方法。

三,== 和equals

3.1,两者之间区边

? ==:

? 对于基本类型来说:==表示数值的比较

? 对于引用类型来说:==表示地址值的比较

? equals:

? 比较的是两者之间值是否相等,但是Java中的类都是直接或者间接继承Object类,而equals不也例外。其实在equals源码中也是使用==进行比较的,如下源码:

  1. ![](https://img2018.cnblogs.com/blog/1655301/201909/1655301-20190902223856542-1095893842.png)?

? 那么问题来了,这和==又有什么区别呢?

? 上面说到equals也是继承自java.lang.Object,因此可以对equals进行重写来定义我们自己的比较方式。

? 请参看以下代码:

  1. String?str1?=?"abc";?
  2. ????????String?str2?=?"abc";?
  3. ?
  4. ????????char[]?strArray?=?{'a','b','c'};?
  5. ????????String?str3?=?new?String(strArray);?
  6. ?
  7. ????????String?str4?=?"abc";?
  8. ?
  9. ????????System.out.println(str1?==?str2);????
  10. ????????System.out.println(str1?==?str3);????
  11. ????????System.out.println(str2?==?str3);????
  12. ????????System.out.println(str4.equals(str1));??

? 以上运行结果为:

  1. true?
  2. false?
  3. false?
  4. true?

? 接下来我们依次分析上面的结果:

? 1,str1与str2比较的是字符串对象地址,因为它们的值是相同的,所以地址值也是相同的。

? 2,str3是new出来的示例对象,在堆内存中会开辟一块新的内存地址,它并不在常量池中。所以返回结果为false。

? 3,同理str2与str3比较也是一样的结果。

? 4,equals比较的是值是否相同,所以返回的结果为true。

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章