关于Integer和反射的一个缓冲区注意事项

本文深入探讨了Java中使用反射修改Integer值时可能遇到的问题,特别是当涉及到自动装箱和Integer缓存时的潜在风险。通过具体示例,揭示了不当使用反射可能导致的缓冲区混乱及数据错误。

关于Integer一些隐藏关卡

Mackyhuang

反射绕过安全保护修改integer时候的典型错误,使用反射强行修改的时候请慎重
Integer在方法中没有提供value的get和set方法,如果现在需要你编写一个函数,使得交换俩个值,你会发现java在这里的值传递在Integer里面是copy了一个副本指向值,而不是直接地址。
那如果就是需要拥有这么一个方法的话,那么应该怎么做呢:
    private static void swap(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException {
		//利用反射修改
        Field field = Integer.class.getDeclaredField("value");
		//绕过安全检查修改final值
        field.setAccessible(true);
		//暂存a的值
        int temp = a.intValue();
		交换
        field.set(a, b);  
        field.set(b, temp)	//参数需要俩个object 所以这里会装箱
        }
}
这段代码不难理解,其实就是:
int temp = a;
a = b;
b = temp 
  • 只不过这里是使用的反射的机制,本质还是不变的;
既然方法编写成功啦,那么我们编写一个main函数开始测试吧!
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Integer a = 1;
        Integer b = 2;
        System.out.println("a = " + a + ", b = " + b);
        swap(a, b);
        System.out.println("a = " + a + ", b = " + b);
 }
  • 在大家心里肯定是已经有答案了吧,不过现在的结果可能会大跌眼镜:

     a = 1, b = 2
     a = 2, b = 2
    
诶!这里为啥俩个值都会变成2呢,其实这里也是让我自己都感觉到不可思议
  • 先让我们知道装箱的概念

  • 如果不理解的可以看看我的另外一篇文章Java装箱和拆箱

  • 现在我们再次看看valueOf这个函数

      public static Integer valueOf(int i) {
          if (i >= IntegerCache.low && i <= IntegerCache.high)
              return IntegerCache.cache[i + (-IntegerCache.low)];
          return new Integer(i);
      }
    
  • 其实这里就是准备-128 到 127 缓冲区来应对高频率的整数使用

      field.set(a, b);  
    
  • 问题就是出现在这一句话里面, 这里的a和b需要看main函数的初始化,不难发现他们就是由自动装箱来的,那么他们俩个其实就是

      a = IntegerCache.cache[1 + -(-128)]  //cache[129]
      b = IntegerCache.cache[2 + -(-128)]	 //cache[130]
    
那么重点来啦,现在field使用反射强行修改值,这样的操作一直都是不安全的操作,这里就是一个非常典型的例子, 这句话直接把缓冲区修改了!
	cache[129] = b.intValue()  // cache[129] = 2;
  • 所以接下来的

      field.set(b, temp)
    
  • 这里set方法参数需要俩个object 所以这里会装箱, 也就是 temp装箱执行代码

      IntegerCache.cache[temp + -(-128)]  // temp = 1
    
  • 结果已经显而易见啦!这个时候的temp装箱以后居然变成了2!所以导致了错误

看到这里已经明了了把,其实就是一句话,

使用反射修改了缓冲区,使得缓冲区完全错乱

那在进行装箱就不会有正确的结果啦,这里为了让大家更加能够理解和看到错误的缓冲区,我们再来一段代码
  • main函数声明

          Integer a = 1;
          Integer l = 1;
          Integer m = 1;
          Integer b = 2;
    
  • 方法中

      	field.set(a, b);
          field.set(b, new Integer(10));
          field.set(3, new Integer(11));
          field.set(5, new Integer(100));
    
  • 输出缓冲区0 到 10 的元素

      	for (int i = 0; i <= 10; i++){
              if(i % 10 == 0){
                  System.out.println("");
              }
              System.out.print(i + " " + Integer.valueOf(i) + " , ");
          }
    
  • 答案

      0 0 , 1 2 , 2 10 , 3 11 , 4 4 , 5 100 , 6 6 , 7 7 , 8 8 , 9 9 
    

现在很清楚了把,缓冲区被轻而易举的修改啦,所以大家要牢记不要滥用反射去修改那些java保护起来的东西,java做好的保护不让你碰其实就是怕你掉进坑了,所以使用反射的时候千万要思考周全以后再来使用

<think>好的,用户的问题是关于如何使用SimTalk编写一个带有缓冲区反馈控制的物料源方法。首先,我需要明确用户的需求。他们可能是在使用像Plant Simulation这样的仿真软件,需要控制物料源的生成速率,基于缓冲区的状态来调整,防止缓冲区过载或空置。 接下来,我应该考虑SimTalk的基本语法结构,确保示例代码正确。缓冲区反馈控制通常涉及检查缓冲区的当前容量,然后根据预设的阈值调整物料源的生成速度或停止生成。例如,当缓冲区快满时,减缓或停止物料生成;当缓冲区有空间时,恢复或加快生成。 然后,我需要设计一个方法的结构,可能包括获取缓冲区的当前容量,设置高低阈值,并根据这些值调整物料源的状态。可能需要使用到SimTalk中的对象引用,比如@.buffer指向缓冲区对象,@指向当前物料源对象。 还需要考虑逻辑判断,比如使用if语句来检查容量是否超过高阈值或低于低阈值,并相应地设置停工或恢复生产的状态。可能需要使用到属性如isStopped来控制物料源的启停。 另外,用户可能需要了解如何将这个方法关联到物料源的循环控制或Exit策略中,确保方法被定期执行。比如,在物料源的Exit字段中设置循环检测,每隔一定时间执行一次checkBufferLevel方法。 最后,生成相关问题,帮助用户深入理解,比如如何动态调整阈值、处理多个缓冲区的情况,或者与其他控制策略结合使用。这些问题应该覆盖实际应用中可能遇到的扩展需求,确保用户能够根据示例进一步调整优化他们的代码。</think>### SimTalk缓冲区反馈控制物料源实现方案 使用Plant Simulation的SimTalk实现缓冲区反馈控制,核心是通过实时监控缓冲区容量动态调整物料生成。以下是标准实现方法: ```simtalk method checkBufferLevel var bufferObj: object currentLevel: integer highThreshold: integer := 80 -- 高水位阈值(%) lowThreshold: integer := 20 -- 低水位阈值(%) bufferObj := @.buffer -- 关联的缓冲区对象 currentLevel := bufferObj.occupiedPercent if currentLevel >= highThreshold then @.isStopped := true -- 停止物料生成 debug "物料源暂停:缓冲区已达", currentLevel, "%" elseif currentLevel <= lowThreshold and @.isStopped then @.isStopped := false -- 恢复物料生成 debug "物料源重启:缓冲区降至", currentLevel, "%" end end ``` **实现逻辑说明**: 1. 通过`occupiedPercent`获取缓冲区实时占用率[^2] 2. 设置双阈值控制策略: - 当占用 ≥80%时停止物料生成 - 当占用 ≤20%且处于停工状态时恢复生产 3. 使用`isStopped`属性控制物料源启停状态 4. 调试信息输出当前控制状态 **部署方式**: 1. 在物料源的`Exit`字段设置循环检测: ```simtalk @.checkBufferLevel wait 60 sec -- 每分钟检测一次 ``` 2. 关联缓冲区对象到物料源的`buffer`属性 **优化建议**: - 添加滞后控制防止频繁启停 - 设置最大停工时长 - 采用模糊逻辑进行动态阈值调整
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值