为什么 类 in javax.mail 将系统属性存储在静态字段中?

Why do classes in javax.mail store system properties in static fields?

我已经 运行 进入 javax.mail 中的 problem handling file names,其中一些方面需要通过会话属性进行配置,一些需要通过系统属性进行配置。 javax.mail 的许多 classes 似乎将它们处理的属性存储在静态字段中,如以下 MimeBodyPart 的示例:

private static final boolean encodeFileName =
PropUtil.getBooleanSystemProperty("mail.mime.encodefilename", false);

根据我的理解,这将系统 属性 的具体值绑定到某些具体 class 加载程序中 class 的生命周期。谁先加载 class,谁就是唯一能够影响该值的人。这正是发生在我身上的事情:

我知道我需要设置一些特定的系统 属性 来影响文件名处理,并且在我处理文件名的地方这样做,为了文档目的等,让事情尽可能靠近。但是对于出于某种原因,之前的代码更早地加载了感兴趣的 class,将错误的值绑定到静态字段。改变它的唯一方法是将我的值设置移动到调用层次结构中较早的位置,但我花了一些时间才注意到静态字段的东西。

这对我来说似乎是一个糟糕的策略,因为我无法轻易知道与我共享相同 classloader 的哪些代码使用相同的 classes。从理论上讲,这将迫使我在启动 JVM 时设置我的系统属性,使我的代码的实现细节成为各种不同情况下的管理细节。如果完全使用系统属性而不是会话一次,我希望这些属性像会话一次一样被实时查询。否则在某些情况和用例下更改相应的设置是不必要的困难。

OTOH,目前的方法可能只是有一些我不知道的好处,比如查询系统属性非常昂贵等等。

那么,MimeBodyPart 做上述事情的充分理由是什么?

你是对的,@maio290,它是故意设计得很糟糕的。 :-)

在多线程应用程序中,动态查询 属性 并没有多大帮助。

在大多数情况下,这些静态属性预计不会在应用程序的生命周期内发生变化。

在某些情况下,static 的使用是一种不幸的妥协,因为需要它的代码无法访问 Session。更改所有 API 以显式传递 Session 会使代码更加复杂。

考虑了线程本地存储,但这在很大程度上取决于应用程序使用的线程模型。

尽可能使用会话属性,但在某些情况下没有好的方法,因此使用系统属性。

From my understanding, this binds the concrete value of the system property to the life of the class in some concrete classloader. Whoever loads that class first, is the only one being able to influence the value. That was exactly what happened to me.

在命令行上设置 属性 更安全,但我理解您反对这样做。根据您的问题,暗示您正在使用 java.lang.System::setProperty 来设置 属性。正如您将在文档中看到的那样,在执行此操作时会出现一些可怕的警告。

根据 API 文档:

API Note: Changing a standard system property may have unpredictable results unless otherwise specified. See getProperties for details.

根据 java.lang.System::getProperties:

API Note: Changing a standard system property may have unpredictable results unless otherwise specified. Property values may be cached during initialization or on first use. Setting a standard property after initialization using getProperties(), setProperties(Properties), setProperty(String, String), or clearProperty(String) may not have the desired effect.

The Java™ Tutorials -> System Utilities -> System Properties

Warning: Changing system properties is potentially dangerous and should be done with discretion. Many system properties are not reread after start-up and are there for informational purposes. Changing some properties may have unexpected side-effects.

简而言之,如果您希望它始终正确设置,则必须使用命令行。