关于PREEvision二次开发的常见问题及解析(上)

本文介绍了PREEvision二次开发中遇到的两个问题:静态变量不自动释放导致的意外行为和修改构件属性默认值不生效。提供了针对这些问题的解决方案,包括初始化静态变量和在GenericEditor中设置默认标记。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在前几期的文章中,我们已经介绍过了PREEvision二次开发的部分使用场景,相信大家对PREEvision二次开发有了一定的了解。本期将主要介绍在开发过程中遇到的一些常见问题以及对应问题的解决方案。

Metric中的静态变量不释放

在PREEvision的Metric中,静态变量通常具有全局作用域,它们在整个应用程序的生命周期内存在,并且不会自动释放。这意味着一旦静态变量被分配内存,它们将一直存在于内存中,直到应用程序终止,这个应用程序终止是指PREEvision软件的关闭而不是当前Metric程序的终止。但有些Metric是需要在PREEvision软件关闭前多次执行,这就会导致下一次Metric程序执行时使用上一次被赋予不正确初值的静态变量。我们可以通过以下程序来了解一下具体问题:

这是一个Metric计算块对应的示例类,它继承自AbstractCalculatableSourceCode类,并重写了calculateResult()方法。在CalculationBlock这个类中,定义了名为num的静态变量,并赋予了初值0,在calculateResult()这个方法中,首先打印了变量num的初始值,然后将其赋值为20,最后再次打印赋值后的值。

根据这段代码的逻辑,每次调用calculateResult()方法时,都会输出num的初始值和赋值后的值。如果多次调用这个方法,应该会得到相同的输出结果,因为赋值操作是确定性的,然而实际的输出结果和预想的并不相同。

可以看到,上面是该Metric执行3次的输出结果,首次执行结果和其他两次执行的结果并不相同,很明显不是我们想要得到的结果,也违背了对于相同的输入只能得到相同的输出的特性。

我们先来分析一下原因:

在Java中,静态变量的生命周期与类的生命周期相同,它们在类加载时被初始化,直到程序结束或该类被卸载时才会销毁。

具体来说,静态变量的生命周期分为以下几个阶段:

  1. 类加载:当JVM第一次加载类时,会为静态变量分配内存并进行初始化。静态变量只会被初始化一次。
  2. 类使用:一旦静态变量被初始化,它们可以在类的任何实例方法、静态方法或构造函数中使用。
  3. 生命周期持久性:静态变量的生命周期与类的生命周期相同。它们会一直存在,直到程序结束或该类被卸载。这意味着静态变量的值在程序运行期间是共享的,对于所有的类实例都是可见的。

总结起来,静态变量在类加载时被初始化,只会初始化一次,并且在类的整个生命周期中都存在。

PREEvision的内部虚拟机是专门为Metric而开发的虚拟机Virtual Validation Machine(VVM),PREEvision的Metric是基于PREEvision内部的虚拟机(VVM)运行的。Metric中定义的静态变量的生命周期和PREEvision的生命周期一致,只有在PREEvison重启后或Metric的代码重新被编译后,静态变量才会被重新的初始化。我们可以从静态变量的使用场景来分析怎么避免再出现上述问题。

静态变量的使用场景如下:

  1. 共享数据:静态变量可以在多个对象之间共享数据;
  2. 常量定义: 静态变量可以用于定义常量,即在整个程序执行过程中都保持不变的值;
  3. 计数器或标识符:静态变量可以用于创建计数器或标识符;
  4. 对象工厂:静态变量可以用于创建单例模式的对象;
  5. 缓存数据:静态变量可以用于缓存数据,以提高性能。

对于Metric的开发,第4点是基本用不到的,而第2点不会受到此问题的影响。我们主要针对其余三点进行优化,即在Metric执行多次时,静态变量能够被正确的初始化。

目前有两种解决方案。

第1种方式是通过每次执行时对此变量进行初始化的方式来解决。

我们可以看到num的输出值是我们想要的结果。

第2种方式是在构造函数中对此变量进行初始化。

这种方式也同样可以达到每次执行Metric时初始化num值的效果。

以上两种方式就是解决此类问题的方法,这两种解决方案实际都是在每次执行时对num进行初始化。这两种方法虽然简单,但是也有缺点,程序每次执行完后,这个变量在内存中是不会释放的,如果这样的变量非常多的话可能会对内存造成一定的影响,并且需要对所有静态变量进行初始化的工作。

当然,该类问题也有其他解决方案,如果Metric需要定义大量的静态变量,我们可以在文件中定义这些变量并且在程序执行时读取该文件,这样不仅简化了静态变量的维护工作,也解决了Metric多次执行后的内存占用问题,这里我们就不一一进行讲解。

Metric中修改构件属性默认值不生效

在PREEvision二次开发中经常会有这样的情况,我们会根据业务逻辑创建某一类构件,然后为这个构件的一些属性赋予初始值,但是在构件的Property View窗口中,属性显示的值并不是正确的。

以SOME/IP Transformer构件为例:

我们在程序中将Mask属性值设置为0,然后进行打印输出。

通过程序的输出可以看到,程序中对Mask属性值的修改是成功的,但是在构件的属性窗口中却还是显示not set。

出现这个问题的原因是由于数值型属性的默认值会在创建时被PREEvision自动设置为0,并在属性窗口中以not set的形式展现出来,当我们在程序中为属性设置0时,PREEvision认为我们并没有改变属性的值,所有不会对构件进行更改。对于该类问题我们可以在Generic Editor窗口中找到解决方法。

在该窗口中我们可以看到Mask属性值确实为0,并且我们也看到所有属性后面都会有两个复选框C和D。在PREEvision中,ChangedMarker(C)和DefaultMarker(D)是两个标记(Marker)的概念。

DefaultMarker(默认标记)用于标识构件的属性是否是默认状态,ChangedMarker(更改标记)用于标识构件的属性是否是修改状态。当对模型中的某个构件属性进行更改时,该构件属性的DefaultMarker值会被设置为false,而ChangedMarker值会被设置为true,以指示该属性已被修改。通过分辨这两个标记,开发人员可以更清楚地了解哪些属性值是默认状态或是已修改状态。

这样我们只需在程序中,通过以下代码告知PREEvision这个属性为非默认状态即可:someIpTransformer.setMaskDefaultMarker(false)。

在构件的Property View可以看到,此时该属性已被成功修改。

以上就是PREEvision二次开发的两个常见问题及解决方法,后续我们还将推出“PREEvision二次开发常见问题解析(下)”,对其他问题进行讲解。如果大家在开发中遇到其他问题,可以联系我们或发送到邮箱market@dotrustech.com,欢迎一起进行讨论。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值