javac符号名字的管理
在符号表中,很重要的一项内容就是符号的名字。名字的管理,要解决的主要问题就是名字的变长问题。在javac中,所有的符号名字放到了一个公用字符池中,对于相同的名字只保存一个。
其中涉及到的主要类及关系如下图。
每个名字都是一个Name对象,所有的Name对象全部存储到了Name类的内部类Table中。这个table就是上面提到的公用字符池。
看一下Table的实现类SharedNameTable类中重要的属性,如下:
- /** The hash table for names.
- */
- private NameImpl[] hashes;
- /** The shared byte array holding all encountered names.
- */
- public byte[] bytes;
- /** The mask to be used for hashing
- */
- private int hashMask;
- /** The number of filled bytes in `names'.
- *
- * `names'中的填充字节数
- */
- private int nc = 0;
这个bytes数组将存储所有的name。其中的某个name是通过起始位置的偏移index和name的长度length来划分的。看一下Name的实现类NameImpl就知道了,如下:
- /**
- * The next name occupying the same hash bucket.
- */
- NameImpl next;
- /** The index where the bytes of this name are stored in the global name buffer `byte'.
- */
- int index;
- /** The number of bytes in this name.
- */
- int length;
那么问题又来了,我如何存储一个新的NameImple以及查找NameImpl呢?看到SharedNameTable类中的hashes属性了吧。为了加快查找速度,通过计算Name的hash值将其映射到n个桶中,每个
桶中的名字构成一个单项列表,使用NameImpl中的属性next相连。
来看一看具体的代码实现就一目了然了。如下:
- @Override
- public Name fromChars(char[] cs, int start, int len) {
- int nc = this.nc; // The number of filled bytes in `names'.
- byte[] bytes = this.bytes; // The shared byte array holding all encountered names.
- // 对公用字符池进行扩容操作
- while (nc + len * 3 >= bytes.length) {
- // System.err.println("doubling name buffer of length " + names.length + " to fit " + len + " chars");//DEBUG
- byte[] newnames = new byte[bytes.length * 2];
- System.arraycopy(bytes, 0, newnames, 0, bytes.length);
- bytes = this.bytes = newnames;
- }
- // chars2utf(char[] src, int sindex, byte[] dst, int dindex, int len)
- int nbytes = Convert.chars2utf(cs, start, bytes, nc, len) - nc;
- int h = hashValue(bytes, nc, nbytes) & hashMask;
- NameImpl n = hashes[h];
- while (
- n != null &&
- (n.getByteLength() != nbytes || !equals(bytes, n.index, bytes, nc, nbytes))
- ){
- n = n.next;
- }
- // 没有查找到时,存储这个新的Name
- if (n == null) {
- n = new NameImpl(this);
- n.index = nc;
- n.length = nbytes;
- n.next = hashes[h];
- hashes[h] = n;
- this.nc = nc + nbytes;
- if (nbytes == 0) {
- this.nc++;
- }
- }
- return n; // 返回查找到的Name
- }
fromChars()方法兼有存储和查找的功能。主要的逻辑就是首先算出Name的hash值,然后去hashes中查找是否已经存储了这个Name属性,主要的判断就是:
- n.getByteLength() != nbytes || !equals(bytes, n.index, bytes, nc, nbytes
如果存储了就直接返回,如果没有存储就新建一个NameImpl,并指定这个NameImpl的index和length属性。返回这个NameImpl。图示如下:
javac符号名字的管理的更多相关文章
- 第六章-Javac符号表
需要参考: (1)Architecture of a Java Compiler (2)关于符号Symbol第一篇 (3)关于符号Symbol第二篇 (4)关于类型Type (5)关于作用域范围Sco ...
- Scanner类中的nextToken()方法解读
下面看一下nextToken()方法的源码实现. 1.Java中的控制字符 case ' ': // (Spec 3.6) case '\t': // (Spec 3.6) case FF: // ( ...
- Javac源码解读-书目录
1.Javac编译器 (1)Javac编译器介绍(主要介绍如何从java源代码到class的一个转换过程) (2)Javac的源码(说明其中哪个功能由哪个主要的类来完成) (3)Javac支持的命令及 ...
- ELF Format 笔记(十五)—— 符号哈希表
ilocker:关注 Android 安全(新手) QQ: 2597294287 符号哈希表用于支援符号表的访问,能够提高符号搜索速度. 下表用于解释该哈希表的组织,但该格式并不属于 ELF 规范. ...
- 【Cocos2d-x 3.x】内存管理机制与源码分析
侯捷先生说过这么一句话 : 源码之前,了无秘密. 要了解Cocos2d-x的内存管理机制,就得阅读源码. 接触Cocos2d-x时, Cocos2d-x的最新版本已经到了3.2的时代,在学习Coco ...
- OFM管理
OMF:oracle management files 作用:不用指定文件的路径大小名字 OMF管理数据文件:db_create_file_dest 传统方式:SQL>create tables ...
- C++名字空间/C++命名空间
0.序言 名字空间是C++提供的一种解决符号名字冲突的方法. 一个命令空间是一个作用域,在不同名字空间中命名相同的符号代表不同的实体. 通常,利用定义名字空间的办法,可以使模块划分更加方便,减少模块间 ...
- Django与supervisor 管理进程
1.前言 在Django项目中,我们需要用到一些独立于Django框架外的脚本.这样一些脚本可能需要独立的持续运行,且具有很强的可维护性,这个时候supervisor就可以排上用场了. 基于pytho ...
- Python 进程管理工具 Supervisor 使用教程
Supervisor 是基于 Python 的进程管理工具,只能运行在 Unix-Like 的系统上,也就是无法运行在 Windows 上.Supervisor 官方版目前只能运行在 Python 2 ...
随机推荐
- Ubuntu的常识使用了解
1 在分区的时候也是有一定的机巧的,根据磁盘的特点,我们知道越是靠磁盘外部的柱面,旋转越快,而且每次旋转时,磁盘读写头可以覆盖较多的区域,也就意味着靠外部的柱面可以得到较好的性能.所以在分区时,我们应 ...
- oracle 索引的分类
1. B树索引(默认索引,保存讲过排序过的索引列和对应的rowid值) 1)说明: 1.oracle中最常用的索引:B树索引就是一颗二叉树:叶子节点(双向链表)包含索引列和指向表中每个匹配行的ROWI ...
- Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)
Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cgl ...
- Bootstrap模态框modal的高度和宽度设置
(1)高度 将style=“height:900px”放在<div class = "modal-dialog">或者更外层上,整个模态框的高度不会发生变化 如下图所示 ...
- mysql 按照时间查询
这篇文章转载自http://blog.csdn.net/wangjuan_01/article/details/51726588 今天 select * from 表名 where to_days(时 ...
- sql server还原到指定时间
BACKUP LOG yjxy_1010 TO DISK='d:\yixy_log.bak' WITH FORMAT 数据库右击->任务->还原->还原事务日志.
- 【转】.NET内存管理、垃圾回收
1. Stack和Heap 每个线程对应一个stack,线程创建的时候CLR为其创建这个stack,stack主要作用是记录函数的执行情况.值类型变量(函数的参数.局部变量 等非成员变量)都分配 ...
- HTML5 Communication API
本文探讨用于构建实时(real-time)跨域(cross-origin)通信的两个重要模块:跨文档消息通讯和XMLHttpRequest Level 2.通过它们,我们可以构建引人注目的Web应用, ...
- Android Performance 性能提升
1. 经常变动的字符串要用 StringBuilder,然后每次变动用 append 方法.而不应该每次创建新的 String. 2. 使用 static final 变量. 3. It's reas ...
- 水平居中和transform: translateY(-50%) 实现元素垂直居中效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...