V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
aguesuka
V2EX  ›  Java

分享 Lombok 一个有意思的 Issue

  •  
  •   aguesuka · 2022-05-19 14:01:39 +08:00 · 3421 次点击
    这是一个创建于 921 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/projectlombok/lombok/issues/2681

    前情提要

    众所周知 Lombok 依赖的一些库上面有这样的标记.

    This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

    这段话傲娇地通知大家它会在未来版本变化而没有通知. 而因为 JEP 396 默认情况下强封装 JDK 内部 的原因, Lombok 不支持 JDK16, 所以有了这个 Issue.

    机翻一些有意思的回复

    回复 A

    作为一名 OpenJDK 开发人员,让我解释一下,我们故意决定(经过大量辩论后)留下一些众所周知的漏洞 (译注: 指编译时添加参数 --illegal-access=permit), 以便让库有更多时间逐步为新现实做准备,并解释它,以及为什么会这样对他们的用户来说绝对必要。 这些漏洞计划从 JDK 17 开始逐步删除,一次一个,因为 16 已经有了封装的第一步。 发布漏洞不会让它们迟早留下或被删除;他们的移除不会被加速或推迟。 它们正在按计划被移除,并且在每个之前都会有几个月的通知。 我建议 library 作者利用这段时间让自己和他们的用户为这个更好但不同的环境做好准备。
    简而言之,策略是这样的:允许库使用 JDK 内部,只要它们通知用户他们正在使用 add-opens 这样做. 这是因为此类库与 JDK 版本相关联,因此在更新时必须保持警惕,并且它们的用户需要了解库可能强加给他们的维护问题 (在运行时执行此操作的库也存在安全问题)。

    所以,你可以做你喜欢的事,但是如果你给你的用户带来了潜在的维护负担,你必须让他们知道。 当所有漏洞都被关闭时,library 将需要决定是不使用内部结构还是让用户适应附加开放。 在某些月份,没有任何方法——使用 Unsafe 、attach 、native code 等——在没有明确批准应用程序的情况下破解 JDK 内部。

    当然,这对于应用程序来说不是问题,它应该嵌入他们自己的运行时和启动器以及他们喜欢的任何标志 (或者,当涉及到构建时间工具时,你可以创建一个 Maven 插件来做到这一点)。 关键是,如果用户不知道并采取一些行动明确允许它——通过使用特定的可执行文件、特定插件或添加标志,就不可能引入维护 (和 /或安全)负担。 当用户明白这是必要的时,他们往往会非常乐于助人。

    回答(前面的被省略了), JDK16 发行后 Java8 比 Java11 更受欢迎, 很真实.

    在提出新的语言特性时,JEP 流程的倾向通常是做一些研究:这种变化的影响是什么?这种影响分析应该考虑到各种库的常见程度 (换句话说,1.4 中添加 assert 作为关键字的“断言”崩溃本不应该发生,因为当时 junit 在整个生态系统中是最常用的单元测试库,1.4 通过引入向后不兼容的更改来打破它:这是一个错误,并且吸取了教训)。

    但显然,这个标准并没有在这里应用。我很乐意看到 OpenJDK 团队仔细研究这个建议的升级路径,使用与语言更改经常要求的类似的想法:考虑实际影响,而不是重重规范。

    请注意,即使在今天,java8 也比 java11 更受欢迎。我很确定 OpenJDK 团队对 jigsaw 项目对 java8 和 java11 之间的兼容性的不利影响的态度是造成这种情况的主要原因。

    • 鉴于所有这些事情,我恳请您将其提交给 OpenJDK 团队,并重新考虑计划--add-opens 和建议的升级路径。你的既定目标不会通过你的计划来实现,而且现在已经有一段时间了。你所做的只是让事情变得更糟:
    • 由于您的计划,Java11 的采用已经倒退了十年。

    我们只是继续解决它,我相当怀疑这种情况会改变。我们总是可以只制作 maven 和 gradle 插件,这可能符合您声明的技术升级路径选项(本质上,我们现在是一个“应用程序”),但并没有实现更清楚地表明正在使用内部 API 的目标;如果有的话,它使弄清楚这一点变得更加困难,而不是更容易,并且它使 java 程序员更有可能因不兼容性而头疼。

    在确保 Java 生态系统减少向后不兼容问题的任务中,您正在积极地引入它们。你是在增加问题而不是解决问题!

    回复 B

    我的问题是,lombok 摆脱对 JDK 内部依赖的长期战略是什么? 它会继续实施额外的变通办法和黑客入侵 javac 吗? 作为 maven 插件发布似乎是解决最近 JDK 更新带来的加强封装的另一种方式。当这些 JDK 内部不再可访问时,将会有一个点,黑客将失败。要么,要么龙目岛将不得不继续使用一种机制,例如 add-opens 保持撬开内部结构。 lombok 真的打算无限期地依赖 JDK 内部吗?

    回答

    @A248(译注: 上一个问题的作者)Lombok 将始终依赖 jdk 内部,因为我们需要参与编译过程。我们不能在编译前或编译后更改代码。

    @pron(译注: 第一个问题的作者)我建议允许库在清单中声明其添加打开的原因是工具 /库维护者知道他们需要什么。我确实理解他们希望对使用非公共 API 持开放态度。但是他们可以通过在清单中声明它来做到这一点。

    允许用户告诉 jvm 他们信任某个库的 java/javac 命令行参数怎么样?
    像:java --module-path x.jar --trust x.jar ...

    下面的文字并不意味着攻击、投诉或任何冒犯性的东西,而只是解释为什么我们在为用户提供最佳体验方面有点敏感。

    郑重声明,我和 Reinier 都赞成允许破坏一些 API 来改进平台。我们有时不同意当权者的选择,并且对支持当权者观点的不一致推理特别敏感。喜欢:我们必须更改此 API ,因为我们认为这是一个好主意,它只会破坏 <1% 的现有程序,但我们不会支持您最喜欢的主题的拉取请求,因为这可能会破坏向后兼容性,即使它是 < 0.1%。

    或者:我们将不再允许 X ,因为这使得它对于不太可能的情况 Y 更加安全,但是修复漏洞 Z ,这是一个很可能的情况,我们不会这样做,因为我们的一些客户依赖关于那个行为。是的,安全是一种权衡。我们接受这一点,我们对此表示赞赏。我们希望用户能够控制这种权衡。通知他们,并为他们提供执行决策的工具。

    11 条回复    2022-05-20 21:22:53 +08:00
    SMGdcAt4kPPQ
        1
    SMGdcAt4kPPQ  
       2022-05-19 14:37:12 +08:00 via Android
    Kotlin 兼容性很好,升级 JDK 没有遇到过问题,Lombok 的功能都有
    beetlerx
        2
    beetlerx  
       2022-05-19 15:51:21 +08:00
    @ComputerIdiot kotlin 大法好
    dk7952638
        3
    dk7952638  
       2022-05-19 16:04:05 +08:00
    lombok 只要不是基于规范来进行开发的,那么兼容性是永远不可避免的,jsr269 目前没有支持修改 AST 的可能性
    Jooooooooo
        4
    Jooooooooo  
       2022-05-19 16:40:02 +08:00
    看这个楼陆陆续续盖了一年多也是不容易...
    dreamlike
        5
    dreamlike  
       2022-05-19 20:04:52 +08:00 via Android
    回复 a 很好啊
    保持兼容性实际上是保持公开接口的语义不变,即使内部再怎么更新也能保持旧有代码的兼容性
    lombok 这种反射去修改 ast 的做法还有某些库依赖于某些内部特定实现(比如说美团那个热加载依赖于 classload 的一个实现)本来就不太好,是一种典型的反模式 会锁死版本
    这种 hack 标准库的行为确实是应该通知用户的,用户不太可能去慢慢去看依赖库的代码实现,jdk 的这个提示很好
    kkkiio
        6
    kkkiio  
       2022-05-20 02:21:10 +08:00
    @dreamlike 写个能用的 JavaBean 得生成 get/set/hashCode/equals 这么多重复代码,这应该不算好的模式吧。kotlin 的`data class`,lombok 的`@Data`,lombok 的流行,都是用户用脚投票的结果,毕竟人生苦短。
    hingbong
        7
    hingbong  
       2022-05-20 08:23:51 +08:00 via Android
    @kkkiio Java 不也有 record class 了
    dreamlike
        8
    dreamlike  
       2022-05-20 09:12:51 +08:00 via Android
    @kkkiio 我并没有在说这种需要一堆 setter 和 getter 模式好,我的意思是在 lombok 这种 hack 标准库的行为不好
    zmal
        9
    zmal  
       2022-05-20 10:40:34 +08:00
    无解的问题。不过 jdk 已经慢慢吸收了一些 lombok 的东西,lombok 也不是不可替代。
    nothingistrue
        10
    nothingistrue  
       2022-05-20 11:20:47 +08:00
    @dreamlike #8 绝对遵照标准,跟不遵照标准,没有区别——死板的标准必然产生为了遵守标准的非标准代码,最终导致标准失效。要说锁版本,几年前 JDK (非 JRE )放弃向下兼容,要比 lombok 更锁版本。
    ychost
        11
    ychost  
       2022-05-20 21:22:53 +08:00
    无解,我也写了一个基于 AST 的编译期 AOP 库,仅支持 java8 后面的版本都难得去兼容,api 说没就没了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5557 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 79ms · UTC 07:02 · PVG 15:02 · LAX 23:02 · JFK 02:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.