当前位置: 首页 > 知识库问答 >
问题:

GC和静态最终字段

阎枫涟
2023-03-14

我们正在开发基于spring boot 2.5.6的支付应用程序。该应用程序托管在docker上,并在Java14上启动。我们创建了一个名为GeneralEnum抽象类,它是@可嵌入的,包含两个变量int-typeString-value。所有枚举类都扩展了这个基类,并在其中定义常量。

这个决定是为了定制整个应用程序层中使用的枚举。你可以在下面看到一个例子:

@Embeddable
public class ShapeEnum extends GeneralEnum {
   public static final ShapeEnum CIRCLE = new ShapeEnum(0, 'Circle');
   public static final ShapeEnum RECTANGLE = new ShapeEnum(1, 'Rectangle');

   public ShapeEnum(int type, String value) {
       super(type, value);
   }
}

该类在实体层中用作嵌入变量,如下所示:

@Entity
public class Shape {
    @Embedded
    @AttributeOverride(name = "type", column = @Columm(name = "shape_type"))
    private ShapeEnum shapeType;
}

系统工作得很好,但是发生了一些错误,ShapeEnum的value字段。RECTANGLE改为Circle,type改为0(!!!)之后,系统会失败(转储内存显示值的变化)。正如我所跟踪的,问题发生在运行GC之后,当ShapeEnum暂时不使用时。

有人知道会发生什么,以及如何解决这个问题吗?目前,重启docker容器会使应用程序正常工作。

提前谢谢。

共有1个答案

扈俊健
2023-03-14

好的,首先我要说问题不在哪里。

这个问题不是由垃圾收集器引起的。GC不会更改变量的值。不是静态变量,也不是实例变量。因此,并不是GC导致一些表示矩形(1)的type字段变为圆形(0)。

你说:

正如我所追踪的,问题发生在运行GC之后,当ShapeEnum有一段时间没有使用时。

这种说法不是确凿的证据。你实际上(可能)说的是,你观察到一个对象的type0,而它本应是1。你(可能)没有观察到实际发生的变化,你(可能)不能确定该值在GC运行前立即是正确的。事实上,你(可能)甚至不能确定该值在GC运行后立即是错误的。

(如果你确实有明确的证据而不是假设,请将其添加到问题中。)

那么到底是什么导致了这种变化呢?

在这个阶段,我们只能猜测。我的猜测是:

>

  • 应用程序的某些部分正在调用setValue方法,但它不应该调用,或者

    您有多个对象来表示(比如说)矩形的枚举。

    我觉得你对这些虚拟枚举的实现很脆弱。它们应该(至少松散地)是不可变的。您可能会修改GeneralEnum类以删除setter,并使类型字段最终。

    如果对象是不可变的,你就不必担心有什么东西会改变它们。还有其他方法可以通过type==1值获得shapenum。等于(“圆”),但不能打断矩形

  •  类似资料:
    • 问题内容: 我找到了一个代码,它声明了如下代码 它们之间有什么区别或相同?还是与或不同? 问题答案: 完全没有区别。根据 Java语言规范的8.3.1-类-字段修饰符, 如果两个或多个(不同的)字段修饰符出现在字段声明中,则按惯例(尽管不是必需的),它们的出现顺序与上面FieldModifier生产中所示的顺序一致。 对于字段,所述生产按以下顺序列出修饰符: 对于方法:

    • 我想知道这样的声明在Java是否有某种真正的意义。我在代码中发现了它几千次,但是我学习和玩字符串,我知道无论你声明一个对象多少次:如果你之前的某个类声明了这个字符串,它就会被汇集并重用(我说的是没有显式构造函数调用而创建的字符串) 事实上,这段代码在调用比较时打印,因此两个变量引用同一个对象。说变量无法重新定义,在这种情况下单词完全没有用。我是不是没抓住重点? 还有几件事: 1 - 为什么显式调用

    • 问题内容: 我一直在 java中的和关键字之间感到困惑。 __ 它们有何不同? 问题答案: static关键字可以在4种情况下使用 静态变量 静态方法 静态代码块 静态嵌套类 首先让我们看一下静态变量和静态方法。 静态变量 它是一个属于类而不属于对象(实例)的变量。 静态变量在执行开始时仅初始化一次。在初始化任何实例变量之前,将首先初始化这些变量。 该类的所有实例共享的单个副本。 静态变量可以通过

    • 问题内容: 我尝试了解通过引用同一封闭类对象初始化静态字段时初始化顺序的行为。 上面这段代码的输出是: 如果我将变量修改为除plain之外的其他任何内容: 输出为: 为什么会这样呢? 请注意,即使同时声明了两者,输出也是如此,在这种情况下,声明之前 问题答案: 静态最终成员先于其他静态成员初始化。 非最终静态成员按出现顺序初始化 因此,在您的第一种情况下: 构造函数在初始化之前首先被调用,因此被显

    • 我有两个UnitTest项目为我的Android项目。一个用于JUnit测试,一个用于Android Unit测试。在JUnit测试项目中,我创建了一个类来访问或设置私有字段、方法或构造函数。(附言:对于那些对完整代码感到好奇的人,请告诉我,我会把它添加到这篇文章的底部。) 我也有UnitTets来测试这些私有方法的访问。现在,所有这些UnitTest都可以工作,接受一个:设置final stat

    • 问题内容: 给定下面的Java代码,您可以在Ruby类中最接近地表示这两个变量吗?而且,在Ruby中是否可以像Java中那样区分和变量? 问题答案: Ruby中确实没有等效的构造。 但是,您似乎犯了一个经典的移植错误:您有一种使用语言A 的 解决方案 ,然后尝试将其翻译为语言B,这时您真正应该做的就是找出 问题 ,然后找出解决方法使用语言B。 我不能完全确定您要从那个小的代码段中解决什么问题,但是