java内存(栈,堆,方法区)

java中内存分为3块分别为:栈、堆、方法区(实际上方法区存在在堆当中也可以说内存分为栈、堆,但是方法区比较特殊所以单独拿出来说)。
1)栈
1、表示方法执行的内存模型,每一个方法被调用时都会创建一个栈帧(栈帧存储在栈当中),栈帧存储局部变量,操作数,方法出口等。
2、jvm会为每一个线程都创建一个栈,用来存放该线程执行方法的信息。
3、栈属于线程私有的,不能实现两个线程的共享
4、栈的存储特性是先进后出,后进先出!
5、栈是系统自动分配的,速度快!栈是一个连续的内存空间!
6、存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

看到这时我想到了一个问题:javaweb中假如从网页上发起了2次请求,这是两个线程,还是属于一个线程?
上网询问得知:同一用户2次请求一个线程,不同用户请求两个线程。(同一个用户可以理解为同一台电脑)

2)堆
1、堆用于存储创建好的对象(数组也是对象)
2、jvm中只有一个堆,被所有线程共享!
3、堆是一个不连续的内存空间,分配灵活,速度慢!、

3)方法区(静态区)
1、jvm只有一个方法区,被所有线程共享!
2、方法区实际上也在堆中,只存储类、常量相关的信息。
3、用来存放程序中永远不变或唯一的内容。(类信息[java代码],class对象,静态变量,字符串常量)

下面是一个关于java内存的代码

public static void main(String[] args) {
        User u1=new User("小明");
        User u2=new User("小明");
        System.out.println(u1.getUserName()==u2.getUserName());
        String a=new String("小明");
        System.out.println(u1.getUserName()==a);
        String b=new String();
        b="小明";
        System.out.println(a==b);
        System.out.println(b==u1.getUserName());
    }

输出打印
true
false
false
true
原理:
1)String创建时,如果是通过=赋值方式创建的话,就会先查询常量池中是否存在该值,如果不存在,在常量池中放入该值,并且栈中的变量引用常量池。
2)如果是new String("小明")这种方式创建的话,那么会将字符串存储在堆中,栈中的变量引用堆。

public static void main(String[] args) {
        String x = "ab";
        change(x);
        System.out.println(x);
}    
public static void change(String x) {
        x = "cd";
}

原理:
开始我看这段代码时,认为打印cd(实际输出ab),我犯了2个错,
1、我错误的认为形参x和变量x为同一个(实际上形参x和变量x是两个)
2、因为认为String类型为引用变量,那么String x和形参x引用同一个常量池的字符串(指向同一个引用)。那么形参x被改变,那么String 相应的被改变。
以下详细的解释第二种错误:
String类型虽然为引用类型但是String类型比较特殊。
String创建时,如果是通过=赋值方式创建的话,就会先查询常量池中是否存在该值,如果存在直接引用常量池,如果不存在,在常量池中放入该值,并且栈中的变量引用常量池。(这样的String它在修改值时,实际上并没有在原来的值上修改,而是相当于在创建[存在引用,不存在常量池种创建再引用]),因此通过=赋值方式的String可以看作和基本类型一样,而通过new String("小明")这种方式创建的可以看作和对象一样。
3、所以以上的代码其实是这样的,栈中存在了2个变量x,String x开始把内存地址拷贝给了形参x(此时它们是一致的),但运行到x="cd"时,它在常量池中创建了一个字符串cd,并且将内存地址引用给了形参x,那么此时形参x和String x并没有引用同一个地址
(形参x引用常量池中的cd,而String x引用常量池中的ab)
而且 change(x);方法过后形参x的生命周期已过(被gc回收),实际上打印的是String x,当然是ab!

关于String使用连接符

String a="小明";
String b="小明";
String c=a+b;
String d="小明小明";
System.out.println(c==d);

1、我错误的认为这里会输出true,实际上输出false,错误理解如下
String a先在常量池中创建了"小明",那么a引用常量池中小明的地址。String b时发现常量池中有"小明",那么ba引用常量池中小明的地址,现在a==b为true。(错误理解开始)String c发现"小明小明"常量池中没有,那么在常量池中创建"小明小明",c的引用指向常量池中的小明小明,String d发现发现"小明小明"常量池中存在,那么d的引用指向常量池中的小明小明。所以c==d为true。

上网查询网友,然后纠正了自己的错误理解,从开始错误的地方开始解释:
String c=a+b;这行代码并没有在常量池当中创建,它是在堆的内存中创建(+号连接符中有变量创建的String就在堆内存中,而不在常量池中)。而d发现常量池中没有"小明小明"那么创建,此时c和d的内存地址当然不同,那么输出false。

如果将以上的代码改为如下代码:

 final String a="小明";
String c=a+"小明";
String d="小明小明";
System.out.println(c==d);

用final修饰a变量的话会输出true,因为
final修饰后就是常量了(不可修改的)。当对这样的字符串常量调用+运算的时候,jvm会在编译的时候进行替换,比如这儿 c = a +"明";因为a是final修饰的,所有会替换为小明,c就相当于c="小明"+“明”
那么String c会在常量池中创建,那么c和的地址相同,那么c==d为true

基本类型的参数传递:
传递的是值的副本,副本的传递不会影响到原件。
引用类型参数的传递:
传递的是对象的地址,副本和原参数都指向了地址。那么改变副本指向对象的值,那么原参数的值也发生了改变。
引用类型中String比较特殊(在上面已经详细说了!)
还有引用类型中的八大类型的包装类也比较特殊(一般情况下可以看作基本类型,但也不一样)
对于包装类说的很好的链接
https://www.cnblogs.com/dolphin0520/p/3780005.html
https://www.cnblogs.com/guodongdidi/p/6953217.html(Integer之间的比较)

对于存储位置很好的链接
https://www.iteye.com/problems/96058

int[] a=new int[0];
一个长度为0的数组其实也在堆内存中开辟了空间!

2019-01-09

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348