V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
peneazy
V2EX  ›  程序员

关于 js 与 Java 堆栈内存的一些疑惑

  •  2
     
  •   peneazy · 2017-04-26 14:02:49 +08:00 · 3106 次点击
    这是一个创建于 2767 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近学习中遇到了些疑惑,希望 v2 各位大牛解惑。

    先说 js ,限定在 ES5 讨论。在 js 中对象是存在堆内存中的,变量只是个引用,那对象的属性是存在哪的呢,假设该属性是个数字 3 ,函数作用域中的变量又是存在哪里呢。

    再说 java , static 修饰的静态变量我理解为和 js 构造函数本身的属性是类似的东西,这东西存在哪块内存,局部变量存在哪块内存,类 new 出的对象中实例变量又存在哪里。

    问题总结:下面两段 java 和 js 代码中, demo.num1 , DemoJava.num2 , num3 , num4 , obj1.num5 , arr1[0]都存在内存哪里?

    public class DemoJava {
    	public int num1 = 1;
    	public static int num2 = 2;
    	public static void main(String[] args) {
    		DemoJava demo = new DemoJava();
    		int num3 = 3;
    		System.out.println("num1:" + demo.num1);
    		System.out.println("num2:" + DemoJava.num2);
    		System.out.println("num3:" + num3);
    	}
    }
    
    var fun1, obj1, arr1;
    
    function add() {
    	var num4 = 4;
    }
    
    obj1 = {
    	num5: 5
    };
    
    arr1 = [6, 7];
    
    21 条回复    2017-04-28 09:55:25 +08:00
    diangdiang
        1
    diangdiang  
       2017-04-26 14:42:26 +08:00
    小白强行回答,貌似 java 类静态变量存在在方法区,局部变量存在栈,通过 new 生成的对象存在堆里,
    《深入理解 Java 虚拟机》有详细介绍。
    araraloren
        2
    araraloren  
       2017-04-26 14:42:50 +08:00
    ~~很好奇
    学 js/java 的人会对这个感兴趣么
    murmur
        3
    murmur  
       2017-04-26 14:45:59 +08:00
    如果是 java 的话其实不绝对,因为你不知道虚拟机把你的东西都优化到哪里去了。。。
    peneazy
        4
    peneazy  
    OP
       2017-04-26 15:03:44 +08:00
    @diangdiang 也看到别人说有个方法区的地方
    peneazy
        5
    peneazy  
    OP
       2017-04-26 15:04:47 +08:00
    @araraloren 没搞明白有些不舒服。。
    peneazy
        6
    peneazy  
    OP
       2017-04-26 15:05:35 +08:00
    @murmur 原来是这样子啊
    sagaxu
        7
    sagaxu  
       2017-04-26 15:18:37 +08:00
    Java 的 Static 存在 Run-Time Constant Pool 里。但是知道它存哪里,毫无意义啊。
    sagaxu
        8
    sagaxu  
       2017-04-26 15:22:32 +08:00
    @peneazy Java 代码如何编译成字节码, JVM 又如何执行和优化, GC 具体是怎么工作的,这些全搞明白,可以读个博了。把 Java 搞懂了, Java 那么多框架和库,把细节搞明白一遍,没个二三十年恐怕不行。
    gxbb097528
        9
    gxbb097528  
       2017-04-26 16:47:32 +08:00
    最近在看网易云课堂的 Java 基础视频,讲的有这些,但是讲的是大概,没有特别深究,要深究真跟楼上说的一样要几个好几年功夫,看看视频了解个大概还行
    geelaw
        10
    geelaw  
       2017-04-26 16:52:19 +08:00
    纠结 JavaScript 的内存布局没有意义, JavaScript 把它抽象掉了。
    guokeke
        11
    guokeke  
       2017-04-26 17:31:24 +08:00
    @geelaw +1
    单从概念上理解,值类型用栈逻辑,引用类型用堆逻辑。
    jun4rui
        12
    jun4rui  
       2017-04-26 17:38:12 +08:00 via Android
    java 的类是引用类型,自然是在堆里面,所有同类共用一块地址
    sagaxu
        13
    sagaxu  
       2017-04-26 17:45:45 +08:00   ❤️ 1
    @jun4rui Java6 开始有了逃逸分析,对象未必会分配在堆上,可能会在栈上分配
    peneazy
        14
    peneazy  
    OP
       2017-04-26 19:00:07 +08:00
    @sagaxu 果然是老司机
    Ouyangan
        15
    Ouyangan  
       2017-04-26 19:25:36 +08:00
    @diangdiang #1 Java8 已经没持久代的概念了 , 也直接在堆上分配内存了.. 详情可以 google 下
    jun4rui
        16
    jun4rui  
       2017-04-26 21:06:42 +08:00
    ```javascript
    var fun1, obj1, arr1;

    //对于 js 来说, function 这种引用值一般是保存在堆内存中的
    function add() {
    var num4 = 4;
    }

    //对象也是, js 中的对象一般是存放在堆内存。所以{num5:5}是保存在堆内存中
    obj1 = {
    num5: 5
    };

    //数组也是存放在堆内存
    arr1 = [6, 7];
    ```

    对于函数作用域应该还是这个标准, function 、 obj 、 array 是在堆,其他基本是在栈
    phx13ye
        17
    phx13ye  
       2017-04-26 21:56:10 +08:00
    实例基本类型和对象一起在堆
    静态基本类型和 class 一起在 permgen 或 metaspace
    方法基本类型和栈帧一起在栈
    runjvm
        18
    runjvm  
       2017-04-27 00:02:32 +08:00   ❤️ 2
    前面很多同学说的都不太准确。
    以 HotSpot 8 为例,静态变量并不存放在方法区或者 PermGen 或者 MetaSpace ,每一个类被解析后都有一个对应的 mirror 对象,这个对象是 java.lang.Class 类型,“方法区”存的只是元数据,譬如描述类的结构、各字段分别什么类型之类的,每一个类的元数据有个指针指向这个对应的 mirror 对象,静态变量是这个 mirror 对象的一个字段, mirror 对象不是只有那些静态变量对应的字段,它还有许多其他的字段用于 reflection 。而 mirror 对象其实都在堆上,于是静态变量作为其一个字段也在堆上。一个 Java 程序一旦运行其实最开始被分配的那些对象就是 primitive 类型对应的 mirror 对象。

    所以短答案是,静态变量的元数据在方法区,但是静态本身在堆上。

    至于前面同学说的逃逸分析,逃逸分析只在编译优化时发生,在解释器里 new 出来的实例对象总是在堆里。
    okcdz
        19
    okcdz  
       2017-04-27 01:03:16 +08:00 via iPhone   ❤️ 1
    回答 js 的问题吧, java 不了解。你这个不是 es5 的问题,而是编译器的问题。对象保存在堆内存里面,对象属性也是。至于小整形,在 v8 实现里面是直接传递的,在 Chakra 里面也是保存在堆里面,然后引用传递。至于函数里的变量,那是运行时分配的空间,当然也是分配在堆里面的。
    araraloren
        20
    araraloren  
       2017-04-28 08:37:43 +08:00
    @peneazy
    但是这种已经隐藏了内部实现的语言,你纠结这个没什么用处
    编译器 可以做各种它觉得可行的优化来提高你的程序执行效率,于是你说的各种情况都可能是片面的
    peneazy
        21
    peneazy  
    OP
       2017-04-28 09:55:25 +08:00
    @araraloren 是啊 已经不纠结这块了,不如多做几道算法题来的爽~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2947 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:06 · PVG 19:06 · LAX 03:06 · JFK 06:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.