自由但受束缚 - Java陷阱
作者:Richard Stallman编者按
自从这篇文章首次发表以来,Sun公司(现已成为Oracle的一部分)已将其大部分Java平台参考实现重新授权在GNU通用公共许可证下,现在有了一个免费的Java开发环境。因此,Java语言本身不再是一个陷阱。
但是,您必须小心,因为并非每个Java平台都是自由的。Sun公司继续分发非自由的可执行Java平台,其他公司也这样做。
Java的免费环境称为IcedTea; Sun公司释放的源代码包含在其中。所以这是您应该使用的。许多GNU/Linux发行版都带有IcedTea,但有些包含非自由的Java平台。(注,2015年10月添加:Java的免费实现在许多GNU/Linux发行版中被称为OpenJDK。)
为了可靠地确保您的Java程序在免费环境中运行良好,您需要使用IcedTea进行开发。理论上,Java平台应该是兼容的,但它们并非100%兼容。
此外,还有一些名称中带有“Java”的非自由程序,例如JavaFX,还有一些非自由的Java软件包您可能会觉得诱人,但需要拒绝。因此,请检查您计划使用的任何软件包的许可证。如果您使用Swing,请确保使用免费版本,该版本随IcedTea一起提供。(注,2015年10月添加:名为OpenJFX的JavaFX免费替代品已发布。)
除了这些Java特有的细节之外,这里描述的一般问题仍然很重要,因为任何非自由库或编程平台都可能导致类似的问题。我们必须从Java的历史中吸取教训,以便将来避免其他陷阱。
另请参阅:JavaScript陷阱。
2004年4月12日
如果您的程序是自由软件,那么它基本上是符合道德规范的——但是您必须警惕一个陷阱。您的程序虽然本身是自由的,但可能会受到它所依赖的非自由软件的限制。由于今天Java程序的问题最为突出,我们称之为Java陷阱。
如果其用户具有某些关键自由,则程序是自由软件。粗略地说,它们是:运行程序的自由、研究和更改源代码的自由、重新分发源代码和二进制文件的自由以及发布改进版本的自由。(请参阅自由软件定义。)任何给定源代码形式的程序是否为自由软件,仅取决于其许可证的含义。
该程序是否可以在自由世界中使用,是否可以被那些希望生活在自由中的人们使用,这是一个更复杂的问题。这不仅仅取决于程序自身的许可证,因为没有程序是孤立工作的。每个程序都依赖于其他程序。例如,程序需要编译或解释,因此它依赖于编译器或解释器。如果编译成字节码,则它依赖于字节码解释器。此外,它需要库才能运行,并且它还可能调用在其他进程中运行的其他单独程序。所有这些程序都是依赖项。依赖项可能是程序运行所必需的,或者它们可能仅对某些功能是必需的。无论哪种方式,没有依赖项,程序的所有或部分都无法运行。
如果程序的一些依赖项是非自由的,则意味着程序的所有或部分无法在完全自由的系统中运行——它在自由世界中不可用。当然,我们可以重新分发该程序,并在我们的机器上拥有副本,但如果它无法运行,那没什么用。该程序是自由软件,但实际上被其非自由的依赖项束缚。
这个问题可能发生在任何类型的软件中,使用任何语言。例如,一个只能在Microsoft Windows上运行的自由程序在自由世界中显然毫无用处。但是,如果软件依赖于其他非自由软件,那么即使在GNU/Linux上运行的软件也可能毫无用处。过去,Motif(在我们拥有LessTif之前)和Qt(在其开发人员使其成为自由软件之前)是导致此问题的主要原因。大多数3D显卡只有使用非自由驱动程序才能完全工作,这也导致了这个问题。但是,今天这个问题的主要来源是Java,因为编写自由软件的人们通常觉得Java很性感。他们被对该语言的吸引力蒙蔽了双眼,忽略了依赖项的问题,并陷入了Java陷阱。
Sun公司对Java的实现是非自由的。标准Java库也是非自由的。我们确实有Java的免费实现,例如GNU Java编译器(GCJ)和GNU Classpath,但它们尚未支持所有功能。我们仍在追赶。
如果您在Sun的Java平台上开发Java程序,您很可能会在不知不觉中使用Sun独有的功能。当您发现这一点时,您可能已经使用它们好几个月了,而重新进行工作可能需要更多个月。您可能会说:“重新开始工作太费力了。”那么您的程序将陷入Java陷阱;它在自由世界中将不可用。
避免Java陷阱的可靠方法是在您的系统中仅安装Java的免费实现。这样,如果您使用自由软件尚未支持的Java功能或库,您将立即发现,并且可以立即重写该代码。
Sun公司继续开发其他“标准”Java库,几乎所有这些库都是非自由的;在许多情况下,即使是库的规范也是商业秘密,而Sun公司对这些规范的最新许可禁止发布任何少于该规范完整实现的内容。(有关示例,请参阅Java规范参与协议和J2ME™个人基础配置文件规范。)
幸运的是,该规范许可允许将实现作为自由软件发布;允许其他接收该库的人员更改它,并且不需要遵守该规范。但是,该要求的效果是禁止使用协作开发模型来生成免费实现。使用该模型将需要发布不完整的版本,而那些已经阅读规范的人员是不允许这样做的。
在自由软件运动的早期,不可能避免依赖非自由程序。在我们拥有GNU C编译器之前,每个C程序(无论是否自由)都依赖于非自由的C编译器。在我们拥有GNU C库之前,每个程序都依赖于非自由的C库。在我们拥有Linux(第一个自由内核)之前,每个程序都依赖于非自由内核。在我们拥有BASH之前,每个shell脚本都必须由非自由的shell解释。我们的第一个程序最初会受到这些依赖项的阻碍是不可避免的,但是我们接受了这一点,因为我们的计划包括随后对其进行营救。我们的总体目标,一个自托管的GNU操作系统,包括所有这些依赖项的自由替代品;如果我们达到目标,我们所有的程序都将被营救。因此,它发生了:使用GNU/Linux系统,我们现在可以在自由平台上运行这些程序。
今天的情况有所不同。我们现在拥有强大的自由操作系统和许多自由编程工具。无论您想做什么工作,都可以在自由平台上进行;即使是暂时的,也没有必要接受非自由的依赖项。人们今天陷入陷阱的主要原因是他们没有考虑这一点。解决此问题的最简单方法是教导人们认识到它并且不要陷入其中。
为了使您的Java代码免受Java陷阱的危害,请安装免费的Java开发环境并使用它。更一般地说,无论您使用哪种语言,都请睁大眼睛,并检查代码所依赖的程序的自由状态。验证程序是否自由的最简单方法是在自由软件目录中查找它。如果程序不在该目录中,则可以将该程序的许可证与自由软件许可证列表进行比较。
我们正在尝试营救被困的Java程序,因此如果您喜欢Java语言,我们邀请您帮助开发GNU Classpath。尝试使用GCJ编译器和GNU Classpath运行您的程序,并报告您在已实现的类中遇到的任何问题也很有用。但是,完成GNU Classpath需要时间;如果继续添加更多的非自由库,我们可能永远不会拥有所有最新的库。因此,请不要给您的自由软件戴上枷锁。当您今天编写应用程序时,请从一开始就编写它以在自由设施上运行。