05 关于局部变量名字的存储

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了05 关于局部变量名字的存储相关的知识,希望对你有一定的参考价值。

@展开剩余8条评论↓ @mazai 验证了一下,变量名称存在局部变量表中了,和静态文件中的那样,不同的是运行时把符号引用Ljava/lang/String 换成了一个虚拟机中的内存地址 [图片]
mazai  21:47:11
符号引用转换成直接引用在解析阶段就会完成
花🌸  21:48:00
[图片]
花🌸 recalled a message
花🌸  21:49:26
所以:常量名称存在局部变量表中,根本不是在什么常量池里
花🌸  21:49:50
谢谢你的源码了
花🌸  21:49:55
@mazai
花🌸  21:50:02
[图片]
壹六得六  21:50:46
。。。你弄明白啥是常量池没有?
花🌸  21:50:49
@展开剩余8条评论↓ 收到自己看一把,目前我能得出的结果,也不知道对不对
mazai  21:51:04
不是啊。。运行时常量池也会有的
花🌸  21:52:35
运行时常量池,存的变量名称--->对应的地址吧
花🌸  21:53:17
针对的是我上面的那个程序哦,不是其它的
壹六得六  21:53:34
。。。随便那个程序都一样。。
mazai  21:53:41
你应该了解一下局部变量表的zuoyong 
壹六得六  21:53:44
编译->装入->运行。。
壹六得六  21:53:50
都是这个流程。。
mazai  21:53:55
[图片]
花🌸  21:54:15
如果是自己定义的类:Person  s1 = new Person() 那这个s1可以在运行时常量池中找到
花🌸  21:54:47
字段名称也可以在常量池找到
mazai  21:54:49
可以啊
mazai  21:55:06
[图片]
mazai  21:55:06
运行时常量池就是存储类信息的
壹六得六  21:55:57
...他把常量池搞的很混的。。
壹六得六  21:55:58
...
壹六得六  21:56:14
编译->装入->运行。。 想想是你,你会咋做
mazai  21:56:42
你实践之前这些概念要了解
mazai  21:56:59
不然你很容易方向走歪的
花🌸  21:57:40
[图片]
花🌸  21:58:10
[图片]这是验证的结果
成都-蓝风  21:59:08
这个应该输出的是 局部变量 的各个 slot 吧 
壹六得六  22:00:20
标识符在编译期 肯定会写入到CLASS里面,作为符号表来管理,装入内存之后,这些标示符全部都要实例化起来
mazai  22:02:42
每个方法会有一个Code属性,Code里面会有一个LocalVaribleTable
mazai  22:03:13
LocalVaribelTable的信息就是从ConstantPool中引入的
花🌸  22:03:25
@成都-蓝风 TopicString对象运行时的数据,我没有看到变量名称,只找到名称对应的地址,然后地址里有值
成都-蓝风  22:04:01
嗯嗯, 你这应该是 使用的 jol 之类的吧 
mazai  22:04:09
不可能没有吧,你是调试的吗
花🌸  22:04:12
@mazai 但是在运行时的常量池里,没有找到变量名称,怎么看你
壹六得六  22:05:07
多读书,自己去找。。
mazai  22:05:23
[图片]
花🌸  22:06:08
你这个是静态的文件呀
花🌸  22:06:10
[图片]
花🌸  22:06:30
[图片]这个是运行时的数据
成都-蓝风  22:07:56
constant pool
 - holder: 0x00000007c008fc30
 - cache: 0x00000001075abfb0
 - resolved_references: 0x00000007bfb662f8
 - reference_map: 0x00000001075ac000
 -   1 : Method : klass_index=5 name_and_type_index=22
 -   2 : String : 'value'
 -   3 : Method : klass_index=4 name_and_type_index=24
 -   4 : Class : 'com/hx/test05/Test18InvokeStatic' 0x00000007c008fc30
 -   5 : Unresolved Class : 'java/lang/Object'
 -   6 : Utf8 : '<init>'
 -   7 : Utf8 : '()V'
 -   8 : Utf8 : 'Code'
 -   9 : Utf8 : 'LineNumberTable'
 -  10 : Utf8 : 'LocalVariableTable'
 -  11 : Utf8 : 'this'
 -  12 : Utf8 : 'Lcom/hx/test05/Test18InvokeStatic;'
 -  13 : Utf8 : 'main'
 -  14 : Utf8 : '([Ljava/lang/String;)V'
 -  15 : Utf8 : 'args'
 -  16 : Utf8 : '[Ljava/lang/String;'
 -  17 : Utf8 : 'name'
 -  18 : Utf8 : 'Ljava/lang/String;'
 -  19 : Utf8 : 'foo'
 -  20 : Utf8 : 'SourceFile'
 -  21 : Utf8 : 'Test18InvokeStatic.java'
 -  22 : NameAndType : name_index=6 signature_index=7
 -  23 : Utf8 : 'value'
 -  24 : NameAndType : name_index=19 signature_index=7
 -  25 : Utf8 : 'com/hx/test05/Test18InvokeStatic'
 -  26 : Utf8 : 'java/lang/Object'
@花🌸 给你一个运行时的吧 
成都-蓝风  22:07:56
[图片]
mazai  22:08:42
[图片]
mazai  22:08:50
这就是运行时数据区的内容啊,运行的时候有可能会添加,但是这些数据还是有的
mazai  22:09:11
我看不懂你的图
成都-蓝风  22:10:43
@mazai 你截图这个 是编译之后class文件里面的信息哦 
mazai  22:11:05
是啊那你们怎么看
壹六得六  22:11:26
。。。肯定会有...
花🌸  22:11:58
我的那个图才是运行时的对象,对象常量池里我是真的没找到
成都-蓝风  22:12:14
上面 花 这个似乎是 HSDB 上面截得吧 
花🌸  22:12:20
@成都-蓝风 你的怎么看的?大哥
花🌸  22:12:22

花🌸  22:13:56
如果是自己定义的类:Person  s1 = new Person() 那这个s1可以在运行时常量池中找到
成都-蓝风  22:14:43
HSDB上面看不到 是因为常量池这部分数据运行时是放在 固定的存储的数据后面的, 这个就需要取了解 常量池的存储方式了 
以及然后 配合 memory viewer 应该能看 
花🌸  22:15:51
我试试
花🌸  22:16:36
那为啥[图片]
成都-蓝风  22:16:49
我觉得 可以暂时不用去关心这个, 其实就是 数据组织的方式而已 
你理解成 常量池 里面有这些东西就行 
花🌸  22:16:51
这个的话,他就能看到呢
成都-蓝风  22:17:02
啊 看啥 
mazai  22:17:20
不用纠结了兄弟
mazai  22:17:22
肯定有的
花🌸  22:17:28
如果是自己定义的类:Person  s1 = new Person() 那这个s1可以在运行时常量池中找到
mazai  22:17:40
没有jvm为啥要加载这些信息?
花🌸  22:18:07
不是纠结,单纯的想验证一下
花🌸  22:18:45
[图片]这个s1在,HSDB能看到
成都-蓝风  22:19:31
[图片]
花🌸  22:21:51
[图片]
成都-蓝风  22:22:41
[图片]
这几个 java.lang.String, 对应的是 局部变量 
花🌸  22:22:45
我只找到变量名称对应的地址,他哥的,头大
花🌸  22:22:57
是的
花🌸  22:23:04
是局部变量
花🌸  22:24:02
类变量我能找得到,常量池里也有 就是[图片]这里面的,找不到
花🌸  22:24:39

Me.S  22:25:27
完美。。。
成都-蓝风  22:25:47
vm 这一层 他不关心具体的变量名字是什么吧, 只是可能 他需要一些额外的支持, 所以 吧这些元数据存下来了 
成都-蓝风  22:26:01
假设 compile 的时候 不生成调试的相关信息 
成都-蓝风  22:26:02
master:test05 jerry$ javap -c -v Test18InvokeStatic.class 
Classfile /Users/jerry/IdeaProjects/HelloWorld/src/main/java/com/hx/test05/Test18InvokeStatic.class
  Last modified May 1, 2020; size 266 bytes
  MD5 checksum aa5c9abbe4f3f629190e8eba1d16157a
public class com.hx.test05.Test18InvokeStatic
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#12         // java/lang/Object."<init>":()V
   #2 = String             #13            // value
   #3 = Methodref          #4.#14         // com/hx/test05/Test18InvokeStatic.foo:()V
   #4 = Class              #15            // com/hx/test05/Test18InvokeStatic
   #5 = Class              #16            // java/lang/Object
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               foo
  #12 = NameAndType        #6:#7          // "<init>":()V
  #13 = Utf8               value
  #14 = NameAndType        #11:#7         // foo:()V
  #15 = Utf8               com/hx/test05/Test18InvokeStatic
  #16 = Utf8               java/lang/Object

  public com.hx.test05.Test18InvokeStatic();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: ldc           #2                  // String value
         2: astore_1
         3: invokestatic  #3                  // Method foo:()V
         6: return

  public static void foo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=0, args_size=0
         0: return

花🌸  22:26:21
不知道了,都不知道怎么验证了,单纯的想验证一下
成都-蓝风  22:26:30
[图片]
你会发现 对应这个例子, "name", 就没有生成了 
敬清  22:27:45
" 花🌸 22:24:02
类变量我能找得到,常量池里也有

就是[图片] "
 局部变量名称也没啥用吧,这名称应该只是在需要生成localVariableTable或者methodParameters才需要再class文件里被描述一下吧@花🌸 
壹六得六  22:28:17
你把你的两个对象放在一起对比一下就知道了。。
敬清  22:28:17
如果不生成这俩个属性表,局部变量名 class文件里都不会被描述
敬清  22:28:30
毕竟虚拟机不关心局部变量名是啥
壹六得六  22:28:41
或者把你那个地址的值转成String出来看就知道了
壹六得六  22:28:59
" 敬清 22:28:30
毕竟虚拟机不关心局部变量名是啥 "
 @敬清 [图片] 要关心
敬清 recalled a message
敬清  22:29:59
我感觉这个名称都不需要加载到虚拟机,只不过是在class文件里描述了一下,以便于反编译啥的
壹六得六  22:30:00
需要加载的
壹六得六  22:30:13
会保存为符号表
花🌸  22:30:48
谢谢蓝风@成都-蓝风
花🌸  22:31:15
[图片]

上面的这部分 我的这部分代码如下 

package com.hx.test05;

/**
 * InvokeStatic
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2020-05-01 15:03
 */
public class Test18InvokeStatic 

  // Test18InvokeStatic
  public static void main(String[] args) 

    String name = "value";
    foo();

  

  // foo
  public static void foo() 

  


以上是关于05 关于局部变量名字的存储的主要内容,如果未能解决你的问题,请参考以下文章

05 关于局部变量名字的存储

存储对已删除 NSManagedObject 的引用的局部变量会发生啥

关于函数返回值为指针类型的分析

关于 global nonlocal 用法

关于JS形参是局部变量的问题

局部函数和全局函数