Linux上的Java编译问题,使用Windows特定的

时间:2013-10-05 13:54:42

标签: java linux windows compilation cross-platform

我在Linux下遇到了编译问题。 我在Linux上编译java程序;目标用途是Linux和Windows。 代码检查是否存在特定于平台的类(如下面的代码所示)。 因此,如果代码在Linux下运行,则不会执行特定的Windows代码。

使用特定于平台的类 Win32MediaTray

会出现问题

报告的编译错误是

PrinterScanner.java:9: error: cannot find symbol
import sun.print.Win32MediaTray;
                 ^

可以在Linux下编译吗?或者只是不可能? 我可以使用一些解决方法(反射?) 毋庸置疑,Windows下的编译没有错误。

谢谢你的帮助。

作为参考,此问题背后的代码如下:

 private String getTrayName(Media media) {

    String result = "id:" + media.getValue();
    boolean isWin32 = media.getClass().getName().equals("sun.print.Win32MediaTray");
    if (isWin32) {
        Win32MediaTray w32 = (Win32MediaTray) media;
        result = result + ",winId:" + w32.winID;
    }
    return result;
}

3 个答案:

答案 0 :(得分:1)

我相信您尝试使用的课程是sun.print.Win32MediaTray

答案是你不能使用它......或者在Linux的Linux版本上编译一个使用它的类。该类未包含在Java发行版的rt.jar文件中。

此外,您不应使用它。 Java文档非常清楚,应用程序代码不应该使用sun.*包层次结构中的类。


如果你别无选择,那么最好的办法是使用反射来获取w32Id字段的值。您还需要处理media对象不是Win32MediaTray类的实例的情况。请注意,您依赖于Oracle特别指出您不应该执行的实现细节。在未来的Windows版本中,它们可能会发生变化(不另行通知!)。

其他选择是:

  • 为每个平台实现您自己的平台适配器类,使用不同的类。这些必须在每个平台上单独编译,然后动态加载。

  • 为每个平台实施单独的代码库。

答案 1 :(得分:1)

为了使编译器满意,您可以实现一个名为sun.print.Win32MediaTray的虚拟类,并使其在编译和运行时类路径中都可用。该类不需要工作,它只需要与API兼容(相同的签名和返回类型,但在这种情况下,您只需要扩展Media并拥有public {{1} } int),这样你就可以同时满足编译器和验证器。

在运行时,由于加载委派,应在Windows上加载winID中包含的版本。在Linux上,虚拟版本是唯一可用的版本,但您声明程序会检查平台并执行另一个代码分支,因此不应该导致程序失败。

例如,在类路径中使用以下类:

rt.jar

我设法在Windows上运行此程序:

package sun.print;

import javax.print.attribute.standard.Media;

public class Win32MediaTray extends Media {
  public int winID = 0xBADC0DE;
  protected Win32MediaTray(int value) {
    super(value);
  }
  static {
    System.out.println("Won't see me on Windows");
  }
}

静态初始值设定项中的消息不会在Windows上打印,因为实际加载的定义是来自public class Main { public static void main(String[] args) { PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService svc : services ) { DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE; Object o = svc.getSupportedAttributeValues(Media.class, flavor, null); if (o != null && o.getClass().isArray()) { for (Media media : (Media[]) o) { if ( media instanceof Win32MediaTray ) System.out.println( ((Win32MediaTray) media).winID ); } } } } } 的定义。显然,代码可以在任何平台上编译。

答案 2 :(得分:0)

如何将使用特定于Windows的内容的代码放入一个单独的jar中;那么你可以在windows上编译并包含那个jar,否则就把它关掉。

执行此操作的一种标准方法是使用应用程序代码使用一个或多个接口;你可以让工厂提供实现类或者用Spring注入它们。但我认为而不是“如何在Linux上编译它”,你的问题应该是“我在针对多个操作系统的应用程序中有这种Windows依赖关系,我该如何处理它?”