Core buffer in Tomcat:org.apache.tomcat.util.buf

在写到coyote的时候,说起过tomcat如何提高性能的手段,就是以专门设计的缓冲区来替代简单的String,让TCP数据以字节的方式存储,非到必要时刻,不进行编码操作、不变成String,那样就可以节省很多cpu时间。具体的实现,就在org.apache.tomcat.util.buf这个包里,这里的类封装了对byte、char缓冲区的操作,诸如读、写、增加缓冲区大小,以及byte、char之间的转换,还有针对URL的编解码。其实就功能上来说,和JDK的NIO颇有些相似,但是更具针对性,专门用于HTTP服务器。研究一下这个,或许对深入理解NIO也有帮助。

ByteChunk

ByteChunk里面,就是一个字节数组buf,同时还有一些start、end等标记数组的有效区间。同时,ByteChunk里面定义了两个接口:ByteInputChannel和ByteOutputChannel。不要被这些channel、chunk之类的字眼给搞糊涂了,在tomcat这里,无非就是:从ByteInputChannel读取数据,放到数组buf,等数组满了就flush到ByteOutputChannel,如此而已。

ByteChunk主要的方法有:append、makespace、equals等,包括重载方法,逻辑都比较简单,也不会牵涉到其他tomcat的类,属于一看就能明白的那种

append方法

基本逻辑是:

  1. 检查参数的正确性,比如是不是null
  2. 如果ByteChunk的limit值小于0,说明不限制,直接System.arraycopy
  3. 假如,要append的数据刚好可以填满buf的剩余空间,那就直接输出到ByteOutputChannel,省了多一次拷贝的时间
  4. 不够空间,则增加buf的大小,但总大小不能超过limit,如果实在装不下,则先把原来的数据flush了再分批装进来

总体来说,这些策略人人都想得到(除了第三点,但这种巧合情况很少发生)

makespace方法

buf扩容的时候,遵循以下几个规则:

  1. 绝对不超过limit
  2. 至少增加256,避免反复扩容,降低效率
  3. 一般至少是原来的两倍体积
equals方法

equals有几个重载方法,首先是参数为String

public boolean equals(String s) {
    // XXX ENCODING - this only works if encoding is UTF8-compat
    // ( ok for tomcat, where we compare ascii - header names, etc )!!!
    byte[] b = buff;
    int blen = end-start;
    if (b == null || blen != s.length()) {
        return false;
    }
    int boff = start;
    for (int i = 0; i < blen; i++) {
        if (b[boff++] != s.charAt(i)) {
        return false;
        }
    }
    return true;
    }

注意这里,注释说明了只能适用于UTF8编码的String,然而看看真正做比较的那行代码,b[boff++] != s.charAt(i) ,我们知道charAt返回一个char,如果String里头包含了中文等不止一个字节的字符时,不知有何后果(UTF8是可变长编码的)。不过,正如注释说的,tomcat只会拿这个类用于处理ascii编码的http头,所以无所谓。

还有一个很有意思的地方,是equalsIgnoreCase方法

通常,我们的实现是,把两个要比较的byte或者char,用String的toLowerCase方法处理后进行比较,但tomcat这里为了提高效率,用了一个特别的设计

Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))

Ascii类是一个静态工具类,它包含了一个256长度的byte数组:toLower[],然后把每个ascii大写字母对应的小写值放进去,别的类使用时就直接取而不必做进一步运算了,等价于保持了一个大小写字母对照表。(也许是jdk本身的大小写转换比较费时)Ascii类的isAlpha、toUpper等也是依据这个思路

hashBytes方法

计算hash code的算法很简单:

for (int i = start; i < max ; i++) {
        code = code * 37 + bb[i];
    }

一个简单的迭代就完了

此外其他startWith、indexOf 等耳熟能详的方法,实现都非常简单,这里就不啰嗦了

java.lang.NoSuchMethodError: org.apache.tomcat.util.buf.UriUtil.isAbsoluteUrl 这个错误是Java编程中常见的错误之一。它表示在运行时,程序在尝试调用org.apache.tomcat.util.buf.UriUtil类的isAbsoluteUrl方法时,找不到对应的方法。可能会出现以下几种情况导致这个错误: 1. 版本不兼容:通常是因为程序在编译时使用了较新的Tomcat库,但在运行时使用的却是较旧的Tomcat库。在较旧的版本中,UriUtil类可能没有isAbsoluteUrl方法,导致调用错误。 解决方法:将编译时和运行时使用的Tomcat库版本保持一致。 2. 缺少依赖:可能是程序所依赖的某个库文件或Jar包丢失或版本不正确,导致UriUtil类无法找到正确的方法。 解决方法:检查程序所依赖的库文件或Jar包是否存在、是否正确引入,并确保它们的版本与程序兼容。 3. 类路径问题:可能是程序无法正确加载org.apache.tomcat.util.buf.UriUtil类,导致无法找到isAbsoluteUrl方法。 解决方法:检查类路径设置是否正确,并确保程序可以正确加载相关类。 4. 代码错误:有可能是程序在调用isAbsoluteUrl方法时传递了错误的参数类型或参数个数,导致方法找不到。 解决方法:检查代码中调用isAbsoluteUrl方法的地方,确保传递的参数类型和个数与方法声明一致。 总结而言,java.lang.NoSuchMethodError: org.apache.tomcat.util.buf.UriUtil.isAbsoluteUrl错误通常是由于版本不兼容、缺少依赖、类路径问题或代码错误导致的。我们需要根据具体情况进行诊断和解决。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值