CodeCache

skynet修改了lua的官方实现(可选),加入了一个新特性,可以让多了lua VM共享相同的函数原型1,当在同一个skynet进程中开启了大量lua VM时,这个特性可以节省不少内存,且提高了VM启动速度.


这个特性的使用,对一般用户来说是透明的,它改写了Lua的辅助API luaL_loadfilex,所有直接或间接调用这个API都会受其影响.比如:loadfile,require等,它以文件名做key,一旦检索到之前有加载过相同文件名的lua文件,则从内存中找到之前的函数原型代替.注:lua函数是由函数原型以及0或多个upvalue绑定而成.


loadstring 不受其影响.所以,如果你需要多次加载一份lua文件,可以使用io.open打开文件,并使用load加载.


代码缓存采用值增加不删除的策略,也就是说,一旦你加载过一份脚本,那么到进程结束前,它占据内存永远不会释放(也不会被加载多次),在大数情况下,这不会有问题.


skynet 留出了接口清理缓存,以做一些调试工作,接口模块叫做skynet.codecache


local cache = require "skynet.codecache"
cache.clear()

这样就可以清理掉代码缓存,这个api是线程安全的,且老版本的数据依旧在内存中(可能被引用),但需注意,单纯靠清理缓存的方式做热更新的方案是不完备的,这个完备性和是否引入这个特性无关,因为当你的系统在加载一批lua脚本时,单靠源文件的更新,无法保证这批脚本加载的原子性(有部分是旧版本,有部分是新版本的)


注意,codecache.clear() 仅仅是创建一个新的cache(api名字容易引起误会),而不释放内存,所以不要频繁调用,如果你需要加载文件不受cache影响,正确的方式是自己读出代码文本,并用loadstring方式加载;而不是在加载前调用codecache.clear


cache.mode(mode)
这个 API 可以修改 codecache 在当前服务中的工作模式。mode 可以是 "ON" "OFF" "EXIST" ,默认的 mode 为 "ON" 。

  • 当 mode 为 "ON" 的时候,当前服务 cache 一切加载 lua 代码文件的行为。
  • 当 mode 为 "OFF" 的时候,当前服务关闭任何重复利用 lua 代码文件的行为,即使在别的服务中曾经加载过同名文件。
  • 当 mode 为 "EXIST" 的时候,当前服务在加载曾经在其它服务或自己的服务加载过同名文件时,复用之前的拷贝。但对新加载的文件则不进行 cache 。注:通常可以让 skynet 本身被 cache 

当 api 参数为空时,返回当前的 mode 。

注意:由于默认模式是打开状态,所以你第一次调用 cache.mode 的所在文件一定是被 cache 的



<think>好的,我现在需要解决用户提出的Java中的java.lang.OutOfMemoryError: Metaspace Code Cache异常问题。首先,我需要理解这个问题的背景和原因。根据用户提供的引用内容,Metaspace在JDK 1.8之后取代了PermGen,用于存储类元数据、静态变量等。而Code Cache则是JVM用来存储编译后的本地代码(如JIT编译后的代码)的内存区域。因此,Metaspace和Code Cache是两个不同的区域,用户提到的异常可能涉及其中一个或两者的组合。 首先,我需要确认用户的问题具体是Metaspace溢出还是Code Cache溢出,或者两者都有。因为异常信息是“Metaspace Code Cache”,可能用户混淆了两者,或者异常信息本身有误。根据引用[1]中的例子,异常是java.lang.OutOfMemoryError: Metaspace,而Code Cache的溢出通常是不同的异常。因此,可能需要进一步确认错误信息的确切内容。不过,假设用户确实遇到了Metaspace或Code Cache的问题,我需要分别分析两者的原因和解决方案。 根据引用[2],Metaspace使用本地内存,而PermGen使用JVM内存。Metaspace的大小默认不受限,但受本地内存限制。如果Metaspace溢出,可能是因为加载了过多的类,或者存在类加载器泄漏。引用[4]提到Metaspace存储类信息和静态变量,如果应用动态生成类(如使用反射、动态代理等),可能导致Metaspace内存不足。解决方案包括调整-XX:MaxMetaspaceSize参数。 而Code Cache溢出则与JIT编译的代码过多有关,尤其是在高负载或长时间运行的应用中,JIT持续编译方法导致Code Cache占满。此时需要调整-XX:ReservedCodeCacheSize参数增大其大小,或者优化代码减少编译量。 用户的问题可能是将两者混淆了,所以需要分别处理。接下来,我需要整理解决方案,包括原因分析、JVM配置参数、调优建议,并引用提供的资料支持。 在回答结构上,需要按照用户要求,分步骤清晰说明,包括错误原因、解决方案、参数配置、调优建议,并生成相关问题。同时,注意使用中文,数学公式用$...$,独立公式用$$...$$,并正确引用提供的参考文献。 需要验证引用的正确性,例如引用[3]提到JVM调优的两个方面:避免异常和性能优化,Metaspace和Code Cache的调整属于第一部分。引用[4]解释了Metaspace的作用,帮助理解溢出的原因。 总结步骤: 1. 分析错误原因,区分Metaspace和Code Cache。 2. 分别给出两者的解决方案和配置参数。 3. 提供调优建议,如监控工具的使用,代码优化。 4. 生成相关问题。 需要确保回答准确,引用正确,例如引用[2]说明Metaspace和PermGen的区别,引用[4]说明Metaspace存储的内容。同时,注意用户可能将Metaspace和Code Cache的问题合并,需要明确区分。</think>### 问题分析:`java.lang.OutOfMemoryError: Metaspace` 与 Code Cache 此错误需明确区分两种内存区域: 1. **Metaspace**:存储类元数据(如类定义、方法字节码、常量池等),默认无上限但受本地内存限制[^2][^4] 2. **Code Cache**:存储JIT编译后的本地机器代码,默认大小因JVM版本而异(通常约240MB) 若错误信息为`Metaspace`或`Code Cache`溢出,需针对性处理。 --- ### 一、原因分析 #### 1. **Metaspace溢出** - 动态生成大量类(如反射、CGLIB动态代理) - 类加载器泄漏(如未释放的OSGi模块) - 未合理配置Metaspace上限 #### 2. **Code Cache溢出** - JIT过度编译方法(如高频调用热点方法) - 未优化代码导致重复编译 - 未调整Code Cache大小 --- ### 二、解决方案与JVM配置 #### 1. **Metaspace配置** ```shell # 设置Metaspace最大值(示例设置为512MB) -XX:MaxMetaspaceSize=512m # 开启类卸载日志(用于诊断类加载问题) -XX:+TraceClassUnloading ``` #### 2. **Code Cache配置** ```shell # 增大Code Cache大小(示例设置为512MB) -XX:ReservedCodeCacheSize=512m # 关闭分层编译(减少编译压力) -XX:-TieredCompilation ``` --- ### 三、调优建议 1. **监控工具**: - 使用`jconsole`或`VisualVM`监控Metaspace和Code Cache使用率 - 通过`jstat -gcutil <pid>`查看内存区域统计 2. **代码优化**: - 避免重复动态生成类 - 减少反射调用频率 - 使用`-XX:+PrintCompilation`分析JIT编译行为 3. **参数调优**: ```shell # Metaspace垃圾回收触发阈值(默认Metaspace占用率超过该值触发GC) -XX:MetaspaceSize=128m # 禁用Code Cache扩展(固定大小) -XX:+UseCodeCacheFlushing ``` --- ### 四、引用说明 - Metaspace与永久代的区别及溢出原因[^2] - JVM调优需避免内存异常并平衡性能[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值