修补 Java 软件

发布于 2024-09-24 02:16:34 字数 388 浏览 10 评论 0原文

我正在尝试创建一个过程来修补我们当前的 java 应用程序,以便用户只需要下载差异而不是整个应用程序。我认为我不需要像二进制 diff 那样低级别,因为大多数 jar 文件都很小,因此替换整个 jar 文件不会有那么大的问题(最多可能 5MB)。

是否有标准工具可以确定哪些文件发生了更改并为它们生成补丁?我见过像 xdelta 和 vpatch 这样的工具,但我认为它们在二进制级别上工作。

我基本上想弄清楚 - 哪些文件需要添加、替换或删除。当我运行补丁时,它将检查软件的当前版本(来自注册表设置)并确保补丁适用于正确的版本。如果是,它将做出必要的改变。听起来这对我自己来说并不太难实现,但我想知道其他人是否已经这样做了。如果这有什么区别的话,我使用 NSIS 作为我的安装程序。

谢谢,

杰夫

I'm trying to create a process to patch our current java application so users only need to download the diffs rather than the entire application. I don't think I need to go as low level as a binary diff since most of the jar files are small, so replacing an entire jar file wouldn't be that big of a deal (maybe 5MB at most).

Are there standard tools for determining which files changed and generating a patch for them? I've seen tools like xdelta and vpatch, but I think they work at a binary level.

I basically want to figure out - which files need to be added, replaced or removed. When I run the patch, it will check the current version of the software (from a registry setting) and ensure the patch is for the correct version. If it is, it will then make the necessary changes. It doesn't sound like this would be too difficult to implement on my own, but I was wondering if other people had already done this. I'm using NSIS as my installer if that makes any difference.

Thanks,

Jeff

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伤感在游骋 2024-10-01 02:16:34

这样做时要小心——我建议根本不要这样做。

最大的问题是公共静态变量。它们实际上被编译到目标中,而不是被引用。这意味着即使 java 文件没有更改,类也必须重新编译,否则您仍然会引用旧值。

您还需要非常小心地更改方法签名——如果您更改方法签名并且不重新编译调用该方法的所有文件,您将遇到一些非常微妙的错误——即使调用 java 文件实际上并不需要更改(例如,将参数从 int 更改为 long)。

如果您决定走这条路,请准备好在客户站点上遇到一些非常难以调试的错误(通常没有痕迹或明显的迹象,只是奇怪的行为,例如收到的数字与发送的数字不匹配),您无法复制这些错误,并且有很多错误惹怒了顾客。

编辑(评论太长):

类文件的二进制差异可能会起作用,但我假设某种版本号或日期被编译进去,并且它们会无缘无故地在每次编译时进行一些更改,但这可能是容易测试。

您可以采取一些严格的开发实践,不使用 public 最终静态(将其设为私有),并且不使用每个更改的方法签名(而是弃用),但我不相信我知道所有可能的问题,我只知道我们遇到的那些。

此外,Jar 文件的二进制差异也是无用的,您必须对类进行差异并将它们重新集成到 jar 中(听起来不容易跟踪)

您可以单独打包资源,然后稍微最小化您的代码吗?拉出字符串(适合 i18n)——我想我只是想知道你是否可以修剪类文件以始终进行完整的构建/发布。

另一方面,Sun 在制作与以前的 JRE 版本完全兼容的类文件方面似乎做得很好,因此他们必须在某个地方有指导方针。

Be careful when doing this--I recommend not doing it at all.

The biggest problem is public static variables. They are actually compiled into the target, not referenced. This means that even if a java file doesn't change, the class must be recompiled or you will still refer to the old value.

You also want to be very careful of changing method signatures--you will get some very subtle bugs if you change a method signature and do not recompile all files that call that method--even if the calling java files don't actually need to change (for instance, change a parameter from an int to a long).

If you decide to go down this path, be ready for some really hard to debug errors (generally no traces or significant indications, just strange behavior like the number received not matching the one sent) on customer site that you cannot duplicate and a lot of pissed off customers.

Edit (too long for comment):

A binary diff of the class files might work but I'd assume that some kind of version number or date gets compiled in and that they'd change a little every compile for no reason but that could be easily tested.

You could take on some strict development practices of not using public final statics (make them private) and not every changing method signatures (deprecate instead) but I'm not convinced that I know all the possible problems, I just know the ones we encountered.

Also binary diffs of the Jar files would be useless, you'd have to diff the classes and re-integrate them into the jars (doesn't sound easy to track)

Can you package your resources separately then minimize your code a bit? Pull out strings (Good for i18n)--I guess I'm just wondering if you could trim the class files enough to always do a full build/ship.

On the other hand, Sun seems to do an okay job of making class files that are completely compatible with the previous JRE release, so they must have guidelines somewhere.

春花秋月 2024-10-01 02:16:34

您可能想看看 Java WebStart 是否可以帮助您,因为它旨在完成您想做的事情。

我知道文档描述了如何创建和进行增量更新,但我们部署整个应用程序,因为它很少发生变化。接下来就是准备好后更新 JNLP 的问题。

You may want to see if Java WebStart can help you as it is designed to do exactly those things you want to do.

I know that the documentation describes how to create and do incremental updates, but we deploy the whole application as it changes very rarely. It is then an issue of updating the JNLP when ready.

dawn曙光 2024-10-01 02:16:34

它是如何部署的?

在本地网络上,我只是将所有内容作为 .class 文件保留在文件夹中。启动脚本使用 robocopy 或 rsync 从网络共享复制到本地。如果任何 .class 文件不同,则会向下同步。如果没有,则不会同步。

对于非本地网络,我创建了自己的更新程序。它下载 md5sums 文本文件并与本地文件进行比较。如果不同,它会从 http 中下载文件。

How is it deployed?

On a local network I just leave everything as .class files in a folder. The startup script uses robocopy or rsync to copy from network share to local. If any .class file is different it is synced down. If not, it doesn't sync.

For non-local network I created my own updater. It downloads a text file of md5sums and compares to local files. If different it pulls file down from http.

你爱我像她 2024-10-01 02:16:34

很久以前,我们解决这个问题的方法是使用类路径和 jar 文件。我们的应用程序是在 Jar 文件中构建的,并且它有一个启动器 Jar 文件。启动器类路径有一个 patch.jar,它在主 application.jar 之前被读入类路径。这意味着我们可以更新 patch.jar 以取代主应用程序中的任何类。

然而,这已经是很久以前的事了。您可能最好使用 Java Web Start 类型的方法,它提供更无缝的应用程序更新。

A long time ago the way we solved this was to used Classpath and jar files. Our application was built in a Jar file, and it had a launcher Jar file. The launcher classpath had a patch.jar that was read into the classpath before the main application.jar. This meant that we could update the patch.jar to supersede any classes in the main application.

However, this was a long time ago. You may be better using something like the Java Web Start type of approach, which offers more seamless application updating.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文