JVM内存分配及String常用方法
一,JVM内存分配和常量池
在介绍String类之前,先来简单分析一下在JVM中,对内存的使用是如何进行分配的。如下图所示(注意:在jdk1.8之后便没有方法区了):
如上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源码中也是使用==进行比较的,如下源码:

那么问题来了,这和==又有什么区别呢?
上面说到equals也是继承自java.lang.Object,因此可以对equals进行重写来定义我们自己的比较方式。
请参看以下代码:
String str1 = "abc";
String str2 = "abc";
char[] strArray = {'a','b','c'};
String str3 = new String(strArray);
String str4 = "abc";
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str2 == str3);
System.out.println(str4.equals(str1));
以上运行结果为:
true
false
false
true
接下来我们依次分析上面的结果:
1,str1与str2比较的是字符串对象地址,因为它们的值是相同的,所以地址值也是相同的。
2,str3是new出来的示例对象,在堆内存中会开辟一块新的内存地址,它并不在常量池中。所以返回结果为false。
3,同理str2与str3比较也是一样的结果。
4,equals比较的是值是否相同,所以返回的结果为true。
如图所示:
四,String常用方法
首先声明字符串:
String str1 = "abc";
4.1,int length()
int length = str1.length();
System.out.println(length);
4.2,char charAt(值)
String str= "abc";
char c = str.charAt(1);
System.out.println(c);
4.3,char toCharArray()
String str= "abc";
char c[] = str.toCharArray();
for (int i = 0; i < c.length; i++) {
System.out.println("转为数组输出:" + c[i]);
}
4.4,int indexOf("字符"); int lastIndexOf("字符")
String str="axcdefgabc";
int a1 = str.indexOf("a");
int a2 = str.indexOf("x", 2);
int a3 = str.lastIndexOf("c");
System.out.println("你的位置为:" + a1);
System.out.println("为的位置为:" + a2);
System.out.println("点最后出现的位置为:" + a3);
4.5,字符串大小写转换
toUpperCase(); 转换成大写
toLowerCase();转换成小写
String str = "hello world";
String str1 = "HELLO WORD";
System.out.println("将字符串转大写为:" + str.toUpperCase());
System.out.println("将字符串转换成小写为:" + str1.toLowerCase());
4.6,String[] split("字符")
String str = "abc,def,123";
String[] arr1 = str.split(",");
4.7,boolean equals(Object anObject)
String str = "abc";
String str1= "123";
if(str.equals(str1)) {
System.out.println("相等");
}
else{
System.out.println("不相等");
}
4.8,String trim()
String str = " abc ";
System.out.println("去掉左右空格后:" + str.trim());
4.9,字符串替换
String replace(char oldChar,char newChar)
String replaceAll(String,String)
将某个内容全部替换成指定内容
String repalceFirst(String,String)
将第一次出现的某个内容替换成指定的内容
String str = "abcdefgabdc";
System.out.println("替换:" + str.replace("abc", "123"));
System.out.println("替换全部:" + str.replaceAll("ab", "12"));
System.out.println("替换第一次出现:" + str.repalceFirst("a", "a"));
4.10,String substring(int beginIndex,int endIndex)
String str = "abcdefg";
// 截取0-3个位置的内容, 不含3
System.out.println("截取后的字符为:" + str.substring(0, 3));
// 从第3个位置开始截取, 含2
System.out.println("截取后字符为:" + str.substring(2));
4.11,boolean equalsIgnoreCase(String)
String str = "ABC";
String str1 = "abc";
if(str.equalsIgnoreCase(str1)){
System.out.println("相等");
}
else{
System.out.println("不相等");
}
4.12,boolean contains(String)
String str = "ABCDEF";
String str1 = "ABC";
if(str.contains(str1)){
System.out.println("str内容中包含ABC");
}
else{
System.out.println("str内容中不包含ABC");
}
五,总结
1,对于JVM内存的分配,在jdk6中存在方法区,jdk8中便没有方法区,改成元区域。
2,jdk6中常量池存在方法区中,jdk7以后常量池移动到堆中。
本篇博客只是简单介绍了JVM内存分配和常量池的概念,仍有很多更深入的原理没有记录。因此在后期会继续更新关于JVM相关的原理知识,以上博客中如有不适之处还请留言(邮箱)指教。
感谢阅读!
JVM内存分配及String常用方法的更多相关文章
- java内存分配和String类型的深度解析
[尊重原创文章出自:http://my.oschina.net/xiaohui249/blog/170013] 摘要 从整体上介绍java内存的概念.构成以及分配机制,在此基础上深度解析java中的S ...
- 最简单例子图解JVM内存分配和回收
一.简介 JVM采用分代垃圾回收.在JVM的内存空间中把堆空间分为年老代和年轻代.将大量(据说是90%以上)创建了没多久就会消亡的对象存储在年轻代,而年老代中存放生命周期长久的实例对象.年轻代中又被分 ...
- JVM 内存分配模型概念和java中各种对象的存储
JVM 内存分配模型概念 --在工作中可能用到的机会不多,有个概念的了解 --此文是转载某位读者,应该是在阅读了<深入理解Java虚拟机JVM高级特性与最佳实践> 一书后,总结所得.写的不 ...
- 最简单例子图解JVM内存分配和回收(转)
本文转自http://ifeve.com/a-simple-example-demo-jvm-allocation-and-gc/ http://www.idouba.net/a-simple-exa ...
- 第二章 JVM内存分配
注意:本篇博客,主要参考自以下四本书 <分布式Java应用:基础与实践> <深入理解Java虚拟机(第二版)> <突破程序员基本功的16课> <实战java虚 ...
- 【转】java内存分配和String类型的深度解析
一.引题 在java语言的所有数据类型中,String类型是比较特殊的一种类型,同时也是面试的时候经常被问到的一个知识点,本文结合java内存分配深度分析关于String的许多令人迷惑的问题.下面是本 ...
- Android性能调优篇之探索JVM内存分配
开篇废话 今天我们一起来学习JVM的内存分配,主要目的是为我们Android内存优化打下基础. 一直在想以什么样的方式来呈现这个知识点才能让我们易于理解,最终决定使用方法为:图解+源代码分析. 欢迎访 ...
- 深入理解JVM内存分配策略
理解JVM内存分配策略 三大原则+担保机制 JVM分配内存机制有三大原则和担保机制 具体如下所示: 优先分配到eden区 大对象,直接进入到老年代 长期存活的对象分配到老年代 空间分配担保 对象优先在 ...
- JVM内存分配与垃圾回收机制管理
项目上线,性能优化有个重要组成就是jvm内存分配和垃圾回收机制的管理配置. 网上随便能搜到相关的具体步骤,以及内存中各种参数对应的意义,不再赘述. 干货就是直接抛出遇到的问题,以及如何解决的,再说说待 ...
随机推荐
- Java集合Collention
集合:又被称为容器,用来存储数据,他是一个对象,能够将具有相同性质的多个元素汇聚成一个整体,集合被用于存储,获取,操纵和传输聚合的数据. 这种数据结构称为集合 Collenction:他是集合的根接口 ...
- 《JSP数据交互总结》
1.1.1为什么需要动态网页 静态网页的内容是固定的,不能提供个性化和定制化的服务,因此,动态网页技术逐渐发展起来. 1.1.2什么是动态页面 动态网页是指在服务器端运行的使用程序语言设计的交互式网页 ...
- HTTP_5_通信数据转发程序:代理、网关、隧道
HTTP通信时,除客户端和服务器之外,还有一些用于通信数据转发的应用程序,例如代理,网关,隧道.配合服务器工作. 代理 转发功能,客户端与服务器之间可有多个代理, 缓存代理:减少服务器压力,透明代理: ...
- ubuntu防火墙规则之ufw
前言 因公司项目的需求,需要对客户端机器简便使用防火墙的功能,所以可在页面进行简便设置防护墙规则,当然,这个功能需求放到我手上我才有机会学到.因为客户端机器都是ubuntu的,所以当然用了ubuntu ...
- 2.2.2python的BeautifulSoup库
from bs4 import BeautifulSoupimport rebroken_html = '<ul class="country"><li>A ...
- S2:面向对象
面向对象七大设计原则 1. 开闭原则 2. 里氏替换原则 3. 单一职责原则 4. 接口隔离原则 5. 依赖倒置原则 6. 迪米特原则 7.组合/聚合复用原则 原则一:(SRP:Single resp ...
- Hadoop 系列(四)—— Hadoop 开发环境搭建
一.前置条件 Hadoop 的运行依赖 JDK,需要预先安装,安装步骤见: Linux 下 JDK 的安装 二.配置免密登录 Hadoop 组件之间需要基于 SSH 进行通讯. 2.1 配置映射 配置 ...
- kali,ubuntu, debain DNS 配置
kali 是基于 debain 的一个 Linux 发行版 DNS 的配置 是在文件 /etc/resolv.conf 下. 但是,我们会发现 /etc/resolv.conf 每次重启都会失效, ...
- oracle RAC LOG_ARCHIVE_DEST_1 与 LOG_ARCHIVE_DEST 冲突解决
在做 oracle RAC 归档日志配置时,出现了一个错误,开始看资料的时候, 注意到了 LOG_ARCHIVE_DEST_n 与 LOG_ARCHIVE_DEST 不能同时使用, 但在配置的时候并没 ...
- mysql docker 主从配置
主从复制相关 前置条件: docker安装的mysql是5.7.26版本 1. 编排docker-compose文件如下: version: '3' services: mysql-master: v ...