-
2020-07-17 11:12:28
java运行时内存分五部分:
线程共享:堆内存、方法区(包括常量池)
线程私有:栈内存、本地方法栈、程序计数器
string不是基本数据类型,那么一个string的内存位置是什么呢?一共有两种情况:
1、string直接赋值:
String s = “haha”;
s的引用存在栈内存中,引用指向的haha存在方法区的常量池中(先判断常量池中是否有一个haha,存在则直接指向)
2、string对象new创建
String s = new String(“haha”);
s的引用存在于栈内存中,引用指向的haha对象,存在堆内存中(每new一次,在堆中创建一个新的haha对象)
总结:
1、string类型的引用,都是存在栈内存中的;
2、string引用指向,直接赋值存在栈内存,new出来的存在堆内存。
更多相关内容 -
Java 字符串常量存放在堆内存还是JAVA方法区?
2021-04-15 16:19:04JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。JDK1.8开始,取消了Java方法区,取而代之的是位于直接内存的元空间(metaSpace)。已知:String A...JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。
JDK1.8开始,取消了Java方法区,取而代之的是位于直接内存的元空间(metaSpace)。
已知:
String A="abc";
String B="abc";
String C=new String("abc");
String D=new String("abc");
比较A==B是否相等?
比较C==D是否相等?
分析:我们知道基本数据类型(int,byte,char...)这些是可以用==比较的,因为他们没有地址,只有值。
但String是类,所以用==比较的时候,判断的是地址是否相同,所以这里C和D是不等,他们是new出来的两个完全不同的对象,仅仅是值相等,就像是两个人仅仅是名字相同。
那么A==B吗?
A、B并不是通过new的方式创建的,所以他们的地址取决于后面所赋的值。Java中,普通字符串存储在常量池中,常量池目前位于堆内存中,所以,从赋值方面来看,此时的A==B是成立的,比较的是常量池里的值。
总结:一般对于对象,比较值是否相等的时候,都是通过覆写equals方法和hash方法来比较的,string用的频繁所以这里是特例,针对性的优化。
-
Java中对象及常量,局部变量,全局变量的存储位置
2020-09-10 17:07:27常量存放在常量池中,而常量池在堆内存中 3.Java中局部变量的存储位置 局部变量存放在栈内存中 4.Java中全局变量和Static常量的存储位置 存放在全局数据区内存中 5.java中static修饰的成员变量及参数存放位置 存放在...Java把内存划分为以下bai4个部分:
1、栈区(stacksegment)—由编译器自动du分配释放,存放函数的参数zhi值,局部变量的值等,具体方法dao执行结束之后,系统自动释放JVM内存资源。
2、堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收。
3、静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放。
4、代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域。here
1Java中对象的存储位置
String aa = new String();
new创建的对象存储在堆内存中;
aa这个局部变量存储在栈内存中;
2.Java中常量的存储位置
常量存放在常量池中,而常量池在堆内存中
3.Java中局部变量的存储位置
局部变量存放在栈内存中
4.Java中全局变量和Static常量的存储位置
存放在全局数据区内存中
5.java中static修饰的成员变量及参数存放位置
存放在方法区 -
浅谈JAVA中字符串常量的储存位置
2021-02-12 18:46:26在讲述这些之前我们需要一些预备知识:Java的内存结构我们可以通过两个方面去看待它。从该角度看的话Java内存结构包含以下部分:1、栈区:由编译器自动分配释放,具体方法执行结束后,系统自动释放JVM内存资源。其...在讲述这些之前我们需要一些预备知识:
Java的内存结构我们可以通过两个方面去看待它。
从该角度看的话Java内存结构包含以下部分:
1、栈区:由编译器自动分配释放,具体方法执行结束后,系统自动释放JVM内存资源。
其作用有保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用。也可以用来保存加载方法时的帧。
2、堆区:一般由程序员分配释放,JVM不定时查看这个对象,如果没有引用指向这个对象就回收。
其作用为用来存放动态产生的数据,包括new出来的实例,字符数组等。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。
因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
3、代码区:存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域。
4、数据区:用来存放static定义的静态成员。
5、常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。
下图大致描述了JAVA的内存分配
二、从操作系统上的进程的角度。相关定义请参考各种操作系统的资料,例如Linux的话可以参考这个简单的介绍:Linux Processes explained (此方面一般被较少地谈论到,本文对此仅仅做一个稍微的介绍)
这里切记一点:JVM规范所描述的抽象JVM概念与实际实现并不总一一对应。
接来下我们来看一段代码实例与注释:
1 public class TestStringConstant {
2 public static void main(String args[]) {
3 // 字符串常量,分配在常量池中,编译器会对其进行优化, Interned table
4 // 即当一个字符串已经存在时,不再重复创建一个相同的对象,而是直接将s2也指向"hello".
5 String s1 = "hello";
6 String s2 = "hello";
7 // new出来的对象,分配在heap中.s3与s4虽然它们指向的字符串内容是相同的,但是是两个不同的对象.
8 // 因此==进行比较时,其所存的引用是不同的,故不会相等
9 String s3 = new String("world");
10 String s4 = new String("world");
11
12 System.out.println(s1 == s2); // true
13 System.out.println(s3 == s4); // false
14 System.out.println(s3.equals(s4)); // true
15 // String中equals方法已经被重写过,比较的是内容是否相等.
16 }
17 }
那么对于上例代码中提到的编译器的优化,下面将进行更进一步的详细介绍。请看下例代码:
class A {
private String a = "aa";
public boolean methodB() {
String b = "bb";
final String c = "cc";
return false;
}
}
"aa"、"bb"的String对象按JVM规范在Java heap上,在JDK8之前的HotSpot VM实现里在PermGen,在JDK7开始的HotSpot VM里在普通Java heap里(而不在PermGen里);"cc"如果存在的话也一样,但是可能会不存在。
这些String对象属于“interned String”。String是Java对象,根据JVM规范的定义它必须存在于Java heap中,interned String也不例外。Interned String特别的地方在于JVM会有个StringTable存着interned String的引用,保证内容相同的String对象不被重复intern。(这里便是编译器的优化)
这个StringTable怎样实现JVM规范里并没有规定,不过通常它并不保存String对象的内容,而只是保存String对象的引用而已。
从JVM规范看a、b、c变量:
a变量作为A类的对象实例字段,会跟随A的实例在Java heap上。
b变量作为局部变量会在Java线程栈上。
c变量虽然也是局部变量,但因为有final修饰并且有初始化为一个常量值,所以c是一个常量。它可能会被优化掉(就没有c这个变量了),也可能跟b一样作为局部变量在Java线程栈上。
从HotSpot VM的实现看:
当methodB()被解释执行时,输入的字节码是怎样的就会怎样执行,而由于javac的实现不会优化掉变量b,所以调用methodB()时它一定会在Java线程栈上的局部变量区里;当字节码里变量c存在时,它也跟b一样在Java线程栈的局部变量区。
当methodB()被JIT编译执行时,由于局部变量b、c都没有被使用,所以它们经过JIT编译后就消失了,调用methodB()不会在栈上给b或c变量分配任何空间。
通过以上相信大家对于字符串常量的分配区域以及java的内存分配有了一个较为形象的了解。
下面是一些相关知识点的补充与注意事项:
1.分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。
2.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。
3.以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。
4.类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。
-
java常量池在哪?有什么用处?
2021-03-01 07:19:44Java常量池存放地点在哪?如图:在Java6和6之前,常量池一般是存放在方法区中的,到了Java7,常量池就被存放到了堆中,Java8之后,就取消了整个永久代区域,取而代之的是元空间。在运行时常量池与静态常量池都会存放... -
Java中的字符串常量池详细介绍
2020-09-03 23:28:04主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池,需要的朋友可以参考下 -
常量池在JVM内存模型中的位置
2019-01-11 15:44:27分别在JDK1.6与1JDK1.7中运行以下代码 public static void main(String[] args) { List<String> list = new ArrayList<String>(); int i = 0; while (true) { // intern 方法保..... -
Java常量,变量,对象(字面量)在JVM内存中的存储位置
2019-02-26 18:13:09苦苦研究了快一天了,终于找到个“大神精准的总结”了!!!!!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 建议与《JVM存储位置分配》...针对Java中... -
Java 类和对象在内存中的表现形式,栈、堆、方法区、常量池
2021-11-09 22:22:58本文为joshua317原创文章,转载请注明:转载自joshua317博客Java 类和对象在内存中的表现形式,栈、堆、方法区、常量池 - joshua317的博客 Java内存分配与管理是Java的核心技术之一,不管学习任何一门语言,我们要知... -
十分钟读懂java常量池优化技术
2019-03-14 15:48:43面试中经常问道的常量池优化技术,Java中的常量值技术是为了方便快捷的创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果没有则创建一个,创建一个比引用一个要耗时),则在需要重复创建相等... -
jvm字符串常量池在什么内存区域?
2021-03-06 05:41:17问题:字符串常量池分配在什么内存区域? 方法区?永久区? 堆内存?首先明晰几个概念:方法区 - java虚拟机规范的运行时数据区方法区 概念属于 java虚拟机规范的运行时数据区的一部分. 运行时数据区包括: 程序计数器、... -
分析Java内存分配的栈和堆以及常量池.doc
2020-01-22 11:13:54分析Java内存分配的栈和堆以及常量池 一java虚拟机内存原型 寄存器我们在程序中无法控制栈存放基本类型的数据和对象的引用但对象本身不存放在栈中而是存放在堆中堆存放用new产生的数据静态域存放在对象中用static... -
在Java中定义常量字符串?
2021-03-08 02:11:34我有一个常量字符串列表,需要在Java程序中的不同时间显示它们。在C语言中,我可以在代码顶部定义以下字符串:#define WELCOME_MESSAGE"Hello, welcome to the server"#define WAIT_MESSAGE"Please wait 5 seconds"#... -
Java 常量池
2021-12-11 14:34:15Java 文件被编译成 Class 文件,Class 文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项就是 Class 常量池,Class 常量池是当 Class 文件被 Java 虚拟机加载进来后存放各种字面量 (Literal)和符号... -
JAVA常量池中存储的常量是什么
2021-02-26 12:09:29下面我把e69da5e887aa3231313335323631343130323136353331333262356165当初所搜集的一些资料以及自己的理解贴出来给你看看(比较多,需要耐心点看,呵呵):理解Java常量池JVM运行时数据区的内存模型由五部分组成:... -
深入解析JVM之内存结构及字符串常量池(推荐)
2020-08-18 18:54:46Java作为一种平台无关性的语言,其主要依靠于Java虚拟机——JVM,接下来通过本文给大家介绍JVM之内存结构及字符串常量池的相关知识,需要的朋友可以参考下 -
java面试 : JAVA中 常量的储存位置
2019-01-29 19:52:57常量池:存放字符串常量和基本类型常量(public static final) 常量池:JVM为每个已...由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存... -
JAVA中定义常量方法
2021-02-12 09:17:53在Java语言中,主要是利用final关键字(在Java类中灵活使用Static关键字)来定义常量。当常量被设定后,一般情况下就不允许再进行更改。如可以利用如下的形式来定义一个常量:finaldouble PI=3.1315。在定义这个常量时... -
Java常量,变量,对象(字面量)在内存中的存储位置
2019-06-13 13:37:11针对Java中的常量,变量,字面量,对象的存储,略作总结. ...总结:new出的对象存储堆中,””存储常量池中,基本类型字面量为常量或静态变量时,存储在常量池,为成员变量存储在堆中,为局部变量存储在栈中. ... -
Java中常量定义的几种方式
2021-02-12 09:18:04不过我觉得提取出来并不会有利于代码性能提升,因为常量分配在内存的常亮池中,所以内存不会出现多个相同常量字符串。总的来说提取常量主要是为了避免魔法数字和硬编码等,提高代码的可读性。1、Interface定义常量... -
Java堆、栈和常量池——内存剖析
2013-04-26 17:02:06Java堆、栈和常量池——内存剖析 -
java常量与变量的区别
2021-02-27 13:49:35java常量与变量的区别一、常量用final修饰(也称最终变量)常量在声明时必须赋初值,赋值后不能再修改值常量名通常用全大写字母表示声明时需要添加final或static final类型修饰符,例如:private final int PI=3.... -
Java常量,变量,对象(或字面量)在内存中的存储位置
2019-03-19 13:53:57Java虚拟机(2)-Java常量,变量,对象(或字面量)在内存中的存储位置 -
java常量定义总结 转载
2021-02-12 18:33:04一、常量定义的基本注意事项在Java语言中,主要是利用final关键字(在Java类中灵活使用Static关键字)来进行Java常量定义。当常量被设定后,一般情况下就不允许再进行更改。在定义常量时,需要注意如下内容:一是Java... -
Java 常量池详解(一)字符串常量池
2022-03-13 18:15:21包装类对象池是不是 JVM 常量池的一种? Java创建new String会产生多少个对象 -
java中的常量和变量
2021-02-28 19:16:35变量含义:在程序过程中变量的值会发生变化,直白来说就是用来存储可变化的数据变量的好处:使内存空间的得到重复利用举个例子:1 System.out.println(10);2 System.out.println(10);3 System.out.println(10);这三... -
Java中静态成员及常量池的存储位置
2021-04-08 23:26:58在JDK1.8以后,永久代被移除,此时方法区的实现更改为元空间,但由于元空间主要用于存储字节码文件.class,因此静态成员的存储位置从方法区更改到了堆内存中 Java中,常量池的存储位置 JDK1.6及以前 在JD -
JAVA java学习(19)——————java 常量、常量值(字面常量)、常量定义、常用转义字符
2020-10-24 08:32:25在 Java 中使用 final 关键字来修饰常量。 虽然常量名也可以用小写,但为了便于识别,通常使用大写字母表示常量。 常量值 常量值又称为字面常量,它是通过数据直接表示的,因此有很多种数据类型,像整型和字符串型...