如何避免Microsoft非标准JavaSDK的潜在危险
2008-01-05 08:59:16 来源:WEB开发网核心提示:─ ─Microsoft在其实现的java 1.1要害类库中所增加或省略的方法、类和变量 摘 要Sun 在 宣 布 其 控 诉Microsoft 违 反Java 兼 容 性 问 题 协 议 的 起 诉 中 提 出, 对Java 关 键 类 库 的 修 改 是 错 误 的,如何避免Microsoft非标
─ ─Microsoft在其实现的java 1.1要害类
库中所增加或省略的方法、类和变量
--------------------------------------------------------------------------------
摘 要Sun 在 宣 布 其 控 诉Microsoft 违 反Java 兼 容 性 问 题 协 议 的 起 诉 中 提 出, 对Java 关 键 类 库 的 修 改 是 错 误 的。 在 本 文 中,JavaWorld 投 稿 人、Java 开 发 者John Zukowsk 对Microsoft 新 的SDK 中 到 底 增 加 和 省 略 了 那 些 类、 方 法 和 变 量 做 了 简 明、 全 面 的 总 结。 本 文 提 供 了Sun 和 其 他 公 司 仅 仅 暗 示 的、 在Microsoft Java SDK 中 发 现 的 修 改 的 全 面 列 表, 以 及 每 个 修 改 的 含 义 和 开 发 者 如 何 定 位 任 一 改 变/ 增 加/ 省 略。 总 之, 本 文 说 明 了 用Microsoft 产 品 创 建 真 正 的" 编 写 一 次, 随 处 运 行" 的 应 用 和 创 建 在Microsoft Internet EXPlorer 4.0 上 运 行 的 程 序 时 所 必 须 知 道 的。
Microsoft Internet Explorer 4.0 和2.0 版 的Java SDK 均 已 推 出。 根 据Microsoft Win32 Java 虚 拟 机 的 发 布 注 释,IE 4.0 与 新 的SDK 中 的Java 虚 拟 机 是 相 同 的。 将SDK 中 的Java 类 文 件 与Sun 的Java SDK 1.1.4 release 中 的 文 件 比 较, 就 会 明 白 为 什 么Sun JavaSoft 部 的 总 裁Alan Baratz 说"Microsoft 欺 骗 性 地 修 改 了 关 键 类, 并 加 入 到 其SDK 中" 参 见10 月 份 新 闻。
我 分 析 了 类, 遇 到 了 七 个 方 面 的 问 题。 如 果 要 用Microsoft Java SDK 开 发 在 其 他Java 1.1 认 证 的 环 境 中 可 以 运 行 的 应 用, 应 该 特 别 注 意 这 些 问 题, 它 们 是:
1. 新 类
2. 新 方 法
3. 新 变 量
4. 更 改 的 接 口
5.com.ms 包
6. 省 略 的 方 法
7. 动 作 差 别
Baratz 在Sun 宣 布 其 起 诉 时 用" 欺 骗" 一 词 是 因 为SDK 中 所 带 的 关 于Java 类 的 文 档 没 有 提 到 这 些 修 改。 要 发 现 它 们, 必 须 用SDK 所 带 的ClassVue 工 具 或 者 人 工 地 读 源 代 码。 最 好 使 用ClassVue, 因 为SDK 提 供 的 源 代 码 可 能 并 不 是 产 生 类 的 文 件, 对 不 熟 悉ClassVue 的 人, 等 价 的 工 具 是Sun SDK 提 供 的 类 文 件 内 部 检 查 器javap。
以 下 是 一 张SDK 中 所 有 修 改 的 清 单, 但 是 也 有 可 能 有 疏 漏。 这 里 提 到 的 所 有 修 改 都 在java.lang、java.io、java.awt、java.util 和java.security 包 或 子 包 中, 每 个 包 的 修 改 如 下:
java.lang: 新 方 法、 新 变 量
java.io: 省 略 方 法
java.awt: 新 类、 新 方 法、 新 变 量
java.util: 新 方 法、 新 变 量
java.security: 修 改 接 口
新 类
首 先,Microsoft 在 其Java SDK 系 统 包 中 增 加 了 新 的 类、 方 法 和 变 量。 所 有 在 完 全 修 饰 名 中 以java.* 开 头 的 叫 做 系 统 包 或 者 核 心Java API。 十 六 个 新 类 加 入 到 了java.awt 中, 它 们 是:
Microsoft 新 增 加 的AWT 同 位 类 的Java 类 WButtonPeer WCheckboxMenuItemPeer WCheckboxPeer WChoicePeer
WLabelPeer WListPeer WMenuBarPeer WMenuItemPeer
WMenuPeer WPopupMenuPeer WScrollbarPeer WScrollPanePeer
WTextAreaPeer WTextComponentPeer WTextFieldPeer WUipeer
除 了 最 后 一 个, 所 有 的 类 都 是AWT 构 件 的 同 位(peer) 类。 同 位 类 是 诸 如 按 钮 和 菜 单 的 图 形 构 件 在 特 定 平 台 的 表 示。 一 般 来 说, 这 些 类 会 出 现 在 不 同 的 包 中, 如sun.awt.windows 或 者sun.awt.motif, 你 可 以 不 使 用 它 们, 故 很 容 易 避 免。WUIPeer 也 是 一 个 同 位 类, 但 是 它 支 持Microsoft 专 用 的 动 作, 应 该 避 免 使 用 它。 另 外 还 加 入 了 其 他 的 包 私 有(package-PRivate) 类( 也 称 为 友 类, 无 须 增 加 访 问 分 类 符 关 键 字), 如_AwtUIBand 和_UIMenuRoot。 因 为 在java.awt 之 外 是 不 可 访 问 的, 故 不 能 直 接 使 用。
新 方 法 和 实 例 变 量
增 加 最 多 的 方 法 是getBaseName()。 幸 好 它 是 包 私 有 的。 其 他 的 修 改, 例 如 将classLoader 的loadClassInternal() 方 法 由 包 私 有 变 为 私 有 是 由 于 实 现 上 的 差 别, 不 影 响 开 发 者。
不 是 我 忽 视Microsoft 的 包 私 有 修 改, 但 是 除 非 开 发 者 自 己 扩 展Java 关 键 类 库, 否 则 就 涉 及 不 到 这 些 修 改。 因 为 开 发 者 更 多 的 时 候 是 寻 求 一 种 跨 平 台 的 解 决 方 案, 而 不 是 将 自 己 的 修 改 加 入 到 关 键Java 类 库 中 去, 所 以 这 不 是 问 题。 而 真 正 的 问 题 是Microsoft 新 加 入 的 公 用 方 法。
关 键Java 类 库 中 加 入 的 公 用 方 法 类 新方法
java.awt.EventQueue _postEvent(AWTEvent)
java.awt.Font getNativeData()
java.awt.image.ColorModel finalize()[was protected]
java.awt.image.DirectColorModel getToolkitData()
java.awt.image.IndexColorModel getOpaque()
getToolkitData()
java.awt.SystemColor getWin32Index()
java.lang.Class getInterface(string)
getMethods(int[])
getMethodFromSignature(string,String)
getDeclaredMethodFromSignature(String,String)
java.lang.Runtime getNativeServices()
java.lang.SecurityManager checkFileDialog()
checkMultimedia()
checkRegistry(int,String)
checkSystemStreams(int)
java.lang.VerifyError getAuditDetails()
getAuditIdentifier()
getClassName()
getMethodName()
getPC()
getViolationCode()
getViolationDescription()
java.lang.reflect.Method getDescriptor()
getParameterCount()
java.util.Locale Locale(String,String,String,int,int)
getCodePage()
getDefaultLocaleList()
getLCID() [was private]
getLocaleFromLCID(int)
java.util.ResourceBundle getMenu(String)
getMenuBar(String)
除 非 你 只 在Microsoft 的 环 境 中 运 行 你 的Java 程 序, 否 则 就 应 该 避 免 使 用 这 些 方 法。 除 此 之 外 还 有 三 个 新 的 实 例 变 量 和 为 数 不 少 的 国 际 化 地 区 变 量。
加 入 到Java API 中 的 实 例 变 量 类 新变量
java.awt.Font pData
java.awt.SystemColor appWorkspace
java.lang.reflect.Member PUBLIC_DECLARED
java.util.Locale AFRIKAANS
ALBANIAN
AUSTRALIA
BASQUE
BELGIAN
BELGIAN_FRENCH
BRAZILIAN
BULGARIAN
BYELORUS
CATALAN
CROATIAN
CZECH
DANISH
DUTCH
ESTONIAN
FINNISH
GERMAN_AUSTRIAN
GERMAN_SWISS
GREEK
HEBREW
HUNGARIAN
ICELANDIC
INDONESIAN
IRELAND
JAPANESE_VERTICAL KOREAN_VERTICAL
LATVIAN
LITHUANIAN
MEXICAN
NEWZEALAND
NORWEGIAN
NORWEGIAN_NYNORSK
POLISH
PORTUGESE
ROMANIAN
RUSSIAN
SERBIAN
SIMPLIFIED_CHINESE_VERTICAL
SINGAPORE
SLOVAKIAN
SLOVENIAN
SOUTH_AFRICA
SPANISH
SPANISH_MODERN
SWEDISH
SWISS
THAI
TRADITIONAL_CHINESE_VERTICAL
TURKISH
UKRANIAN
PUBLIC_DECALRED 对Member 是 全 新 的,appWorkspace 对SystemColor 也 是 全 新 的, 而pData 则 由 私 有 变 为 公 用。 与 其 他 修 改 一 样, 必 须 避 免 使 用。 就Locale 对 象 而 言,Microsoft 环 境 支 持 另 外 几 种 语 言, 而JavaSoft 不 支 持。 虽 然 不 使 用 这 些 新 的 地 区 变 量 要 求 你 格 式 化 消 息 时 做 额 外 的 工 作, 但 是 还 是 应 该 避 免 使 用, 而 用 必 要 的 参 数 自 己 创 建 一 个Locale 对 象。
对 每 个 新 加 入 的 地 区 变 量, 在java.text.resource 包 中 都 加 入 了 两 个 公 用 类, 因 为Sun 的docUCentation 特 别 声 明, 不 应 该 直 接 调 用text.resource 中 的API, 所 以 这 也 不 是 问 题。
接 口 修 改
接 口 定 义 了 类 必 须 遵 循 的 部 分 摸 板,Microsoft 修 改 了 部 分 安 全 接 口 摸 板:
Java 安 全 接 口 中 增 加 的 方 法 接口 新方法
java.security.interfaces.DSAPrivateKey getAlgorithm()
getEncoded()
getFormat()
getParams()
java.security.interfaces.DSAPublicKey getAlgorithm()
getEncoded()
getFormat()
getParams()
当 创 建 一 个 实 现 某 一 接 口 的 类 时, 必 须 定 义 接 口 中 声 明 的 每 个 方 法。Microsoft 增 加 了 接 口 中 的 方 法 数 量, 破 坏 了 所 有 实 现 以 前 接 口 的 类。 若 要 创 建 在Microsoft 和 非Microsoft 环 境 中 都 能 运 行 的 程 序, 只 要 你 在 类 中 实 现 了 修 改 的 接 口, 就 必 须 实 现 其 中 增 加 的 方 法。
com.ms 包
com.ms 是 一 组 与Microsoft 建 议 的Java 实 现 一 起 发 表 的 类。 所 有 的 类 在com.ms 包 中, 所 以 用Netscape Navigator/Communicator 和Java 1.1 都 无 法 访 问。 如 果 你 使 用 了com.ms 包 中 的 类, 便 失 去 了 可 移 植 性。 以 下 是 一 个 例 子: 一 个 不 知 情 者 用getFontMetrics() 从Toolkit 类 中 获 取FontMetrics, 此 方 法 的 签 名 说 明 也 是"public FontMetrics getFontMetrics()", 此 方 法 返 回com.ms.awt.FontMetrics 的 一 个 实 例。 如 果 你 将 它 看 作 一 个FontMetrics, 那 么 你 的 程 序 只 能 在Microsoft 的Java 虚 拟 机 上 运 行。 而 如 果 你 坚 持 用FontMetrics, 则 可 以 移 植。
但 是 避 免 使 用com.ms 时 也 有 一 个 例 外,com.ms.ui 中Microsoft 应 用 程 序 基 础 类(AFC) 是 用Java 写 的, 所 以 可 以 使 用。 然 而, 如 果 你 不 使 用IE 4.0, 就 得 单 独 提 供AFC。( 除 非Microsoft 将AFC 类 捆 绑 到 在 非Microsoft 环 境 中 可 用 的 东 西 上, 否 则 必 须 单 独 提 供AFC, 因 为AFC 类 包 含 在IE4 中, 而 其SDK 依 赖Microsoft Java 虚 拟 机 特 性。AFC 类 不 久 将 会 捆 绑 到 其 他 浏 览 器 上, 如Netscape Navigator 3.0。 详 细 信 息 参 看Microsoft 站 点。)
SDK 中 得 省 略
在 我 检 查 过 的 类 中, 只 从Microsoft 建 议 的Java 1.1 实 现 中 省 略 了 一 个 方 法。 省 略 此 多 余 的 方 法 相 对 来 说 并 不 重 要。 确 切 地 说,ByteArrayOutputStream 中 接 受 字 符 编 码 名 参 数 的toString() 方 法 省 略 了。 对 此 省 略 的 回 避 办 法 是 请 求 流 的 字 节 数 组(toByteArray()), 然 后 使 用 接 受 编 码 名 的string 构 造 器。 用 这 两 步, 即 使 用JDK, 也 能 建 立 在Microsoft 运 行 时 环 境 中 运 行 的 程 序。
差 别
最 后 我 要 讨 论 的 这 些 修 改 与 新 增 加 的 类 和 省 略 的 方 法 无 关, 而 与 动 作 上 的 差 别 有 关。 无 论 何 时, 只 要 有 一 个 新 的 环 境 推 出, 你 就 有 必 要 弄 清 楚 它 与 你 期 望 的 动 作 有 和 不 同。 例 如,Netscape Navigator 3.0 beta 5 推 出 时, 浏 览 器 向 程 序 报 告 额 外 的AWT 事 件, 如 果 你 的 程 序 没 有 考 虑 额 外 的 事 件, 就 会 不 正 常 动 作。 对 新 的SDK, 我 们 又 得 面 对 这 种 差 别。
起 初Microsoft Win32 Java 虚 拟 机 声 称 是Java1.1( 注 意 在"1.1" 的 第 二 个1 后 面 没 有 东 西)。 现 在,Sun 推 出 了Java 1.1.4 版 本 的SDK, 这 意 味 着 在Microsoft Java 虚 拟 机 中 并 未 包 括 你 所 期 望 的 错 误 修 正。 也 有 可 能 因 为 实 现 上 的 差 别 或 者Microsoft 自 己 修 正 了 这 些 错 误, 并 不 需 要Sun 的 这 些 错 误 修 正。 然 而 只 要 看 一 眼 源 代 码 并 作 比 较, 就 会 发 现 明 显 的 功 能 差 别。 如 果SDK 并 未 按 照 你 的 期 望 动 作, 你 需 要 适 当 地 调 整 你 的 程 序。
例 如 使 用java.awt.BorderLayout, 当 你 增 加 一 个 没 有 方 位 名(quadrant name) 的 构 件 时, 在JDK 或 者Java 运 行 时 环 境(JRE) 中, 它 会 出 现 在 中 间 方 位 上。 当 增 加 一 个 非 法 方 位 名 的 构 件 时, 如"TOP",BorderLayout 便 抛 出 一 个IllegalArgumentException 异 常。 然 而 在Microsoft 环 境 中 运 行 同 一 个 没 有 方 位 名 的 程 序, 构 件 根 本 就 不 会 在 任 何 地 方 显 示( 影 响Swing JFrame 构 件 使 之 不 可 用 )。 另 一 个 差 别 是 在Microsoft 环 境 中,Dialog 类 接 受 一 个 空 的 父Frame 参 数。 而Sun JDK 中 则 抛 出 一 个IllegalArgumentException 异 常。 越 多 地 在IE 4.0 下 运 行 程 序, 这 些 差 别 就 会 越 多 地 显 现 出 来。 对 于 更 倾 向 于 技 术 的 读 者, 这 里 有 一 些 更 进 一 步 修 改 的 细 节。 其 他 的 动 作 差 别, 其 中 一 些 是 对 原 来 系 统 的 提 高, 对 开 发 者 是 不 可 见 的。 例 如, 对 象 锁 定 可 以 在 不 同 级 上 实 现。 Microsoft 所 做 的 任 何 提 高, 有 望 在SDK 中 得 到 体 现, 反 之 亦 然。Microsoft 环 境 中 额 外 的 性 能 提 高 也 会 反 映 到SDK 中。 例 如, 在Microsoft 环 境 中, 要 改 变 一 个 构 件 的 颜 色 或 字 体 时, 先 检 查 新 值 是 否 与 旧 值 不 同, 如 果 相 同, 不 做 改 变。 而 在Sun 的 环 境 中, 即 使 是 不 必 要 的, 也 盲 目 地 做 改 变。 象 这 样 的 小 的 修 改 可 能 导 致 很 大 的 性 能 提 高。
结 果
毫 无 疑 问,Microsoft 对Java 关 键 类 库 做 了 修 改。Microsoft 能 否 合 法 地 与Sun 达 成 协 议, 完 全 掌 握 在 法 院 的 手 中。 虽 然 总 的 来 说, 这 些 修 改 相 对 较 小, 但 毕 竟 是 修 改 了。 如 果 法 院 因 为 这 些 修 改 不 重 要 而 宣 布 其 不 碍 大 局, 那 么 如 何 阻 止 其 他 修 改 呢 ?
以 下 我 们 快 速 回 顾 一 下 这 些 修 改, 以 及 对 开 发 者 及 用 户 带 来 的 问 题。
不 支 持RMI 和JNI: 如 果 程 序 需 要 这 些 功 能, 则 不 能 正 常 运 行。 开 发 者 必 须 与Sun 的Java 运 行 时 环 境(JRE) 一 起 发 布 程 序, 以 保 证 有 一 个 兼 容 的 环 境。 这 就 导 致 有 些 在 浏 览 器 中 作 为 小 程 序 运 行 得 更 好 的 程 序, 也 必 须 转 换 为 一 个 单 独 的 应 用 程 序。
增 加 的 类、 方 法 和 变 量: 要 开 发100% 纯Java 解 决 方 案, 开 发 者 就 要 避 免 使 用。 虽 然 这 比 较 容 易 实 现, 但 是 当 开 发 者 不 小 心 使 用 了 这 些 不 可 移 植 的 特 征 时, 没 有 类 似 于@ 的 标 志 来 警 告 他 们。 如 果 开 发 者 粗 心, 只 有 等 到 在Microsoft Win32 虚 拟 机 以 外 的 环 境 中 运 行, 程 序 终 止 运 行 或 者 根 本 就 不 启 动 时, 用 户 才 会 发 现。
在 接 口 中 增 加 方 法: 与 下 一 点 一 起, 这 可 能 是 最 大 的 错 误 之 一。 实 现 被 改 变 接 口 的 类 在Microfoft 环 境 中 运 行 的 可 能 性 是 微 乎 其 微 的。 要 使 这 些 类 运 行, 你 必 须 引 入 相 同 命 名 和 相 同 功 能 的 方 法。 为 了 创 建 在Microsoft 和 非Microsoft 环 境 中 都 运 行 的 解 决 方 案, 开 发 者 必 须 定 义 由Microsoft 扩 展 接 口 规 定 的 命 名 和 动 作 的 方 法。 否 则, 以 前 使 用 这 些 接 口 的 可 运 行 的 解 决 方 案 将 不 能 在Microsoft Win32 虚 拟 机 上 运 行。
省 略ByteArrayOutputStream 方 法: 虽 然 这 个 省 略 的 方 法 相 对 并 不 重 要, 但 是 这 可 能 是 最 大 的 错 误 之 一。100% 纯Java 程 序 可 能 在Netscape Navigator 或JDK/JRE 中 运 行 得 很 好, 但 就 是 不 能 在Microsoft 环 境 中 运 行。 除 非 间 接 地 使 用 了 此 方 法, 否 则 很 容 易 绕 开 它。 然 而 对 已 分 发 的 产 品, 这 意 味 着 无 尽 头 地 浪 费 的 技 术 支 持 时 间。 可 能 必 须 更 新 和 重 新 分 发 产 品, 以 支 持Microsoft 的 不 兼 容 环 境。
使 用com.ms 类:Microsoft 没 有 使 用 标 准 的 包 命 名 约 定 - 逆 域 名 命 名 法, 而 使 用 了"ms.com", 它 恰 好 是Morgan Stanley 的 域 名。 应 该 鼓 励 这 种 扩 充。 使 用 其 中 的 大 部 分 功 能 将 使 你 约 束 在Microsoft 环 境 中, 因 此 这 是 开 发 者 必 须 明 确 选 择 的。 不 象 前 面 提 到 的 修 改, 这 些 功 能 不 会 意 外 地 使 用 到。 只 要Microsoft 专 用Java 程 序 被 正 确 地 标 志, 用 户 不 会 有 问 题。
动 作 差 别: 应 用 程 序 编 程 接 口(API) 允 许 实 现 上 的 动 作 差 别。 这 些 差 别 中 有 些 是Microsoft 试 图 减 少1.1 AWT 中 不 兼 容 而 做 的 修 改, 有 些 则 不 是, 而 有 些 带 来 了 性 能 上 的 提 高。 如 果 开 发 者 依 赖 特 定 开 发 工 具, 而 这 种 工 具 存 在 问 题 的 话, 其 中 一 些 差 别 会 给 开 发 者 和 用 户 带 来 困 扰。
结 论
不 幸 的 是,Java 世 界 不 再 太 平。 随 着Java 1.2 第 一beta 版 发 布 的 临 近,Microsoft 表 示 将 不 支 持 其 中 的 部 分 功 能。 这 简 直 就 是IBM 对Apple(PC 对MAC) 的 翻 版。 虽 然Microsoft 和Sun 为Java 工 具 箱 中 包 括 什 么 争 论 不 休, 而 开 发 者 只 是 想 找 份 工 作 做。 谁 最 终 将 会 在 法 院 中 获 胜, 时 间 会 说 明 一 切。 到 那 时, 开 发 者 需 要 理 解 争 论 的 技 术 和 做 有 根 据 的 决 定。 除 非 这 两 个 冤 家 重 新 走 到 一 起, 否 则 用 户 和 开 发 者 就 象 夹 在 老 虎 钳 中, 难 以 做 出 决 定。 虽 然 平 台 间 的 绝 大 部 分 差 别 是 很 小 的, 但 是 毕 竟 存 在。 你 是 放 弃Java 的" 编 写 一 次, 随 处 运 行" 哲 学, 使 用Microsoft 虚 拟 机 的 专 用 扩 展, 还 是 跟 随Sun 的100% 纯Java 原 则 呢 ? 如 果 你 不 需 要JNI 和RMI, 则 很 容 易 选 择。
感 谢 上 帝, 用Microsoft SDK 仍 然 能 创 建100% 纯Java 解 决 方 案。 只 要 避 免 使 用 新 增 到 关 键Java 类 库 中 的 类、 方 法、 变 量, 以 及 不 可 移 植 的com.ms 包, 你 还 能 创 建 跨 平 台 的Java 程 序。 只 要 绕 开 增 加/ 省 略 的 动 作, 你 还 能 用Java 1.1 认 证 的 工 具, 如Sun JDK、JBuilder、VisualAge for Java 或Visual Cafe 2.0 创 建 可 以 在IE 4.0 上 运 行 的 程 序。
更多精彩
赞助商链接