[翻译]JDK 8 兼容性指南
翻译官方文档,译者精力有限,忽略部分划删除线。
译者:坤谷(@JianhaoMo),井桐(@张同宝),激酶
兼容性是一个复杂的问题。 本文介绍了Java平台潜在的三种不兼容问题:
- 源码: 源码兼容性问题关注Java源代码转换成class文件是否兼容,包括代码是否仍然可编译。
- 二进制: 在Java语言规范中,二进制兼容性定义为:”类的改变是二进制兼容的(或者不破坏二进制兼容性),是指如果改变前的类的二进制在链接时没有错误,那么改变后的类在链接时仍然没有错误。”
- 行为 : 行为兼容性包括在运行时执行的代码的语义。 欲了解更多信息,请参阅OpenJDK的开发人员指南 中,兼容性的种类一节。 下面的兼容性文档跟踪相邻的Java版本之间的不兼容。 例如,这个兼容性文档只报告的Java SE 8和Java SE 7的不兼容,而不是以前的版本。 要检查的Java SE 8与早期的Java版本的不兼容性,必须按顺序跟踪一下不兼容性温的。 Java SE 7和JDK 7的兼容性 JDK 6兼容性 J2SE 5.0不兼容问题(自1.4.2)
二进制兼容性
除了下面列出的不兼容问题,Java SE 8与Java SE 7是二进制兼容的。 除了提到的不兼容,Java SE 7编译的类文件将在Java SE8正常运行。而Java SE 8编译的类文件将无法在早期版本的Java SE运行。
源码兼容性
Java SE 8包括新的语言功能和平台的API。这些都在源文件中使用,这些源文件不能在早期版本的Java平台中编译。
一般情况下,源码兼容性策略是避免引入的源代码不兼容问题。 然而,实现Java SE 8的功能所需的更改可能导致代码无法在Java SE的7编译。见Java SE 8和Java SE 7之间的不兼容性和JDK 8和JDK 7之间的不兼容性。
Deprecated API仅用于与早期版本的兼容性支持。除非打开-nowarn
命令行选项,只要使用了Deprecated API,javac编译器就会生成警告信息。 建议应用进行修改,以杜绝使用Deprecated API。
sun.*
包的 一些API在发生了变化。 这些API不供开发人员使用。 开发人员导入sun.*
包,需要自己承担风险。 欲了解更多详细信息,请参阅为什么开发人员不应该编写调用’sun’包的程序。
对于Deprecated API列表,请参阅Deprecated API。
行为兼容性
简而言之,行为兼容性意味着在输入相同时,程序在不同版本的库或平台执行相同(或等同)的操作。 有些平台行为的底层实现是故意设定为未定义的,这样平台发布可以更改。 出于这个原因,建议写代码不依赖于未定义的行为:如果依赖了未定义行为,问题不能算平台不兼容,而是算代码的bug。
Java类文件
Java类文件格式已经更新为Java SE 8版本。 按照JVM规范,Java SE 8的类文件版本是52.0。 由Java SE 8编译器产生的版本为52.0的类文件不能在早期版本Java SE中使用。 下面的文档有Java语言规范(JLS)和Java虚拟机规范(JVMS)的更改信息。
Java SE 8和Java SE 7之间的不兼容性
尽管Java SE 8是与Java平台的早期版本是非常兼容的, 几乎所有现有的程序可以不加修改地运行在Java SE 8,不过JRE和JDK也有一些小的潜在的不兼容性。为了完整性,这里记录极少数情况下”极端案例”。 本节介绍了Java语言的JVM或Java SE API的Java SE 8不兼容。 请注意,此版本中一些API已弃用,有些功能已被完全删除。 虽然这些都是不兼容,他们被列为在单独的列表。 欲了解更多信息,请参阅Deprecated APIs和JDK 8移除的功能。 2015年3月Java SE 8进行了版本维护,不兼容的问题有相应的修改。
JVM:接口默认方法不能触发接口立即初始化 略 不兼容性: 行为 Bug:8043188(译者注:8u40已修复)JVM:JDWP支持接口默认方法和静态方法 略 不兼容性: 行为 RFE:8042123(译者注:8u40已修复)- JVM:对invokespecial指令调用实例初始化方法的校验更加严格 (译者注:只有当前类型或直接超类的实例允许调用) 不兼容性: 行为 REF: 7160765 (译者注:可能是安全相关,无法看到更详细内容)
- JVM:默认每个类文件中都设置了ACC_SUPER标志 Java SE 8以及以上,Java虚拟机默认每个类文件中都设置了ACC_SUPER标志,无论标志在类文件的实际值和类文件的版本的。 该ACC_SUPER标志影响invokespecial的行为。 不兼容性: 行为(译者注:可能是安全相关,无法看到更详细内容)
- JAVA:classes_text支持小语种
当使用DateFormat和SimpleDateFormat来格式化日期时间值时 ,上下文有关的月份名称支持既有格式化形式又有独立形式的小语种。 例如,在捷克语中,
一月
的格式化形式是ledna
,而独立形式是leden
。 DateFormatSymbols的getMonthNames方法和getShortMonthNames方法返回这些语言的月份格式化形式。请注意,直到的Java SE 7,DateFormatSymbols都是返回独立的形式。您可以用Calendar.getDisplayName
方法和Calendar.getDisplayNames
方法来制定返回哪种形式。 请参考API文档。 不兼容性: 行为 RFE:7079560 - 核心库:javax.lang.model引入IntersectionType
在Java SE 8,对于具有multiple bounds的TypeVariables ,
javax.lang.model.type.TypeVariable.getUpperBound
的返回值和早期版本的返回值不同。现在返回新引入IntersectionType的实例,而原来返回DeclaredType的实例。 这可能会导致javax.lang.model.util.TypeVisitor
现有的实现行为改变:之前TypeVariable.getUpperBound
返回multiple bounds变量时调用visitDeclared方法,现在调用visitIntersection方法。 对返回值调用getKind()也能观察到差别。 不兼容性: 行为 RFE: 6557966 -
核心库:non-public java.lang.reflect.Proxy 实现了non-public interface的
java.lang.reflect.Proxy
将是non-public, final, 且非abstract的。 在Java SE 8之前,代理类是public, final, 且非abstract。 - 如果现有的代码不在同一个运行时package里面调用
Proxy.getProxyClass和Constructor.newInstance
方法来创建一个代理实例,它会失败,并抛IllegalAccessException。 对于这样的代码,它需要更改源码为:(1)调用Constructor.setAccessible
设置访问标志设置为true,或(2)使用方便的Proxy.newProxyInstance
方法。 -
如果现有代码试图创建其他运行时package的non-public接口代理,需要授权新的permission
ReflectPermission("newProxyInPackage.{package name}")
。 不兼容性: 源码 - 核心库:java.lang.reflect.Proxy不允许空InvocationHandler
如果给定的InvocationHandler参数为空,
java.lang.reflect.Proxy(InvocationHandler h)
构造函数现在抛NullPointerException。 现有代码使用空参数构造动态代理实例将抛NullPointerException。 这种用法估计很罕见,因为空代理实例无论用在何处都将抛NullPointerException。 不兼容性: 行为 RFE: 4487672 - 核心库:java.math的BigDecimal.stripTrailingZeros的零值问题
Java SE 8之前,如果调用
BigDecimal.stripTrailingZeros
的数值等于零,将返回该值。 现在则返回常量BigDecimal.ZERO
不兼容性质: 行为 RFE: 6480539 - 核心库:java.net的HttpURLConnection响应头引号问题
在以前的版本中HttpURLConnection摘要身份验证实现有误,在WWW-Authenticate响应头中对一些值加了引号。 在Java SE 8版本中,这些值不再加引号。 这是严格遵循
RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
。 一些服务器实现的某些版本已知预期这些值被引用。 HTTP请求到这些服务器可能无法再成功进行身份验证。 而以前由于这些值被加引号而失败的身份验证,可能现在能成功验证。 不兼容性: 行为 RFE: 8010505 - 核心库:java.net的socket非临时端口安全问题 在此版本中,分配给包括不可信代码的所有代码默认socket权限已被更改。 以前,所有代码能够bind任何类型的socket,以及任何大于或等于1024的端口号。此版本仍可以bind socket到每个系统上的临时端口范围。 临时端口的确切范围因操作系统而不同,但通常在高范围(如从49152到65535)。新的限制是bind socket到临时端口范围之外需要显式系统安全策略授权。绝大多数使用客户端TCP socket(开启了SecurityManager)的应用将不会看到任何问题,因为这些通常bind到临时端口。 而使用datagram socket或服务端tcp socket(开启了SecurityManager)应用可能抛安全异常。之前版本不会。 如果发生这种情况,使用者应该检查被请求的端口号是否符合预期。如果符合预期,添加一个socket授权到本地安全策略来解决此问题。 不兼容性: 行为
- 核心库:java.net的DatagramPacket构造函数不再声明异常
在Java SE 8之前,带
java.net.SocketAddress
参数的java.net.DatagramPacket
构造函数,声明抛出java.net.SocketException
。 然而,这个异常永远不会被抛出。 在Java SE 8版本中,该构造函数不再声明抛出java.net.SocketException。 如果的代码catch了SocketException
或它的超类java.io.IOException
,在使用与Java SE 8编译之前删除这些catch块。 不兼容性: 源码 RFE: 8022126 - 核心库:java.util.i18n的LocaleServiceProvider判断Locale问题
选择
LocaleServiceProvider
的机制已经改变。LocaleServiceProvider
的实现现在能够通过overideLocaleServiceProvider.isSupportedLocale
方法来确定Locale是否支持。 然而,如果从JDK7迁移locale service providers, overide此方法对于严格的扩展检查可能涉及与现有应用程序的一些兼容性问题。参考LocaleServiceProvider
类及其isSupportedLocale
方法的描述了解更多细节。 不兼容性: 行为 RFE: 7168528 客户端库:java.awt 略 不兼容性: 行为 RFE: 7146237- 安全库:javax.net.ssl拒绝客户端初始化的renegotiation
Oracle JSSE provider的新sytem property
jdk.tls.rejectClientInitializedRenego
拒绝客户端初始化的renegotiation 。如果这个sytem property为true。服务端拒绝客户端renegotiation的请求,并且抛出handshake_failure
警报。 不兼容性: 行为 RFE: 7188658 -
Hotspot JVM:gc删除Perm 删除并忽略命令行选项 PermSize和MaxPermSize。 如果使用了这两个选项,会发出如下警告:
Java HotSpot(TM) Server VM warning: ignoring option PermSize=32m; support was removed in 8.0 Java HotSpot(TM) Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
不兼容性: 源码 RFE: 6965548
JDK 8与JDK 7之间的不兼容性
本段描述JDK 8在javac、HotSpot或Java SE API中与JDK 7不兼容之处。 需要注意的是,部分API在本次发布中已经标注为不建议使用,甚至部分特性已经被完全移除。这些不兼容的地方在这里单独列出来。如果需要更多的信息,参看Deprecated APIs和JDK 8移除的功能。
JVM:JDI中接口支持默认方法和静态方法 Java SE 8语言规范为接口引入了静态方法和默认方法,因此JDI规范和具体实现中都已经允许使用这个技术。在JDI中,(译者注:8u40已修复)com.sun.jdi.InterfaceType
类包含了方法Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options)
。 不兼容性: 行为 RFE: 8042123核心库:java.lang的windows中检测登录用户home目录 在windows中检测登录用户home目录的步骤,更新为遵照微软推荐的方法。这处改动对在如下两类情况下可能需要重点关注:1.比较旧的windows版本;2.用户home目录在注册表或环境变量中设置到其他的目录下。 不兼容性: 行为 RFE: 6519127- 核心库:java.lang.reflect的getMethods调用结果
新特性默认方法会影响两个方法Class.getMethod、Class.getMethods的调用结果。
Class.getMethod、Class.getMethods的javadoc继承了Java语言规范的定义。Java SE 8改变了这个规则,以便支持默认方法的同时削减继承于超接口的冗余方法(可参考JLS 8, 8.4.8)的数量。比如说,一个类有两个超接口:I和J,每一个都定义了
int length();
,一般来说,我们认为两个方法都是这个类的成员,但是如果J同样扩展于I,那么在Java SE 8中,这个类仅集成了一个方法:J.length()
。 在Java SE 8发布的时候,Class.getMethod和Class.getMethods的实现并没有随定义的更新而更新(两个方法都会返回非继承的超接口的方法)。从兼容性看,这个区别没那么重要了,而与Java SE 7返回的一致性则是优先考虑的。因此无论如何,当重写方法(如上面提到的J.length
)为默认方法,首先应该要过滤掉其他重写的方法(如上面提到的I.length
)。 从JDK 8u20开始,代码实现改为在重写默认方法时,增加上面提到的过滤的步骤。 不兼容性: 行为 RFE: 8029674 - 核心库:java.text舍入行为问题
在之前版本中,当使用
NumberFormat
和DecimalFormat
类时,在特殊情况下是会发生舍入行为的错误。这种错误行为一般发生在调用format()
方法时,给的值非常接近于格式化字符串所定义的中间位置。在这种情况下,错误的双精度值舍入或不舍入行为就会发生。 举例说,当使用默认推荐的NumberFormatFormat
API:NumberFormat nf = java.text.NumberFormat.getInstance()
,跟着格式化代码nf.format(0.8055d)
,0.8055d值在计算机无法精确地表示为一个二进制的值,而是0.80549999999999999378275106209912337362766265869140625。在这里默认的舍入是”half-even”法(译者注:此舍入模式也称为”银行家舍入法”,主要在美国使用。四舍六入,五分两种情况,如果前一位为奇数,则入位,否则舍去),JDK 7中调用format()
方法会错误的输出0.806,然而正确的值应该是0.805,因为内存中记录的值是小于中间位置的。 在所有可能由程序员自定义样式(而不是默认的样式)的位置里,这个舍入行为被修正。 不兼容性: 行为 RFE: 7131459 - 核心库:java.util.collections的removeAll,retainAll不接受null
在之前的版本中,一些
Collection.removeAll(Collection)
和retainAll(Collection)
的实现会静默的忽略传入null参数的情况。从这个版本开始,如果集合传入一个null参数,将会抛出一个NullPointerException
。 不兼容性: 行为 RFE: 8021591 - 核心服务:java.management强制管理接口public
在规范中提到的管理接口需要是puclic的,在这个版本中变成强制的了。非public的接口不存续暴露管理功能,所有的MBean和MXBean接口必须是public的。
系统属性
jdk.jmx.mbeans.allowNonPublic
用于恢复成之前允许非public管理接口的行为。这个属性是过渡期使用的,在后续的发布版中将会被移除。 不兼容性: 行为 客户端库:java.awt 在java.awt.Component.setFocusTraversalKeys()
方法中,如果参数keystrokes里的任何对象不是AWTKeyStroke的话,会抛出ClassCastException(之前是IllegalArgumentException)。 不兼容性: 行为- 安全库:java.security限制com.sun.media.sound
com.sun.media.sound
添加到了JDK 8受限制包列表中。在SecurityManager下运行的应用无法访问这个包及其下各层级,除非得到明确的授权。com.sun.media.sound
包一个内部的、不受支持的包,这相当于是说这不应该被外部的应用所使用。 不兼容性: 源码 RFE: 8019830 - 其他库:corba限制se及其子包 JDK内部包com.sun.corba.se及其子包已被添加到受限包列表中,运行SecurityManager情况下无法直接访问。 不兼容性: 行为 RFE: 8021257
- 工具:javac改正二进制比较的类型规则 Java语言规范(JLS)的15.21章节中关于二进制比较的类型规则没有正确的被javac实施。从JDK 5 版本开始,javac根据JLS规范15.21章节接受了一些类型不正确的对象-原生类型比较的程序。这些比较现在会被认为是类型错误。 不兼容性: 行为 RFE: 8013357
-
工具:javac参数和方法的注解拷贝到合成桥接方法 在这一次发布中,参数和方法的注解将会拷贝到合成桥接方法。这个修复意味着现在程序类似:
@Target(value = {ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @interface ParamAnnotation {} @Target(value = {ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MethodAnnotation {} abstract class T<A,B> { B m(A a){return null;} } class CovariantReturnType extends T<Integer, Integer> { @MethodAnnotation Integer m(@ParamAnnotation Integer i) { return i; } public class VisibilityChange extends CovariantReturnType {} }
每一个生成的桥接方法拥有所有的注解,参数注解也将会复制。这种行为上的改变将会影响一些注解处理器或任何使用注解的普通的程序。 不兼容性: 行为 RFE: 6695379
-
工具:javac参数注解会拷贝到自动生成的内部类构造器 参数注解会拷贝到自动生成的内部类构造器中。这个修复意味着现在如下的程序:
@Target(value = {ElementType.PARAMETER}) @interface ParamAnnotation {} public class initParams { public initParams(@ParamAnnotation int i) {} public void m() { new initParams(2) {}; } }
方法
m()
里,内部类生成的构造器中,参数int i
会有一个注解@ParamAnnotation
。这个行为的变化可能影响一些注解处理器,或者使用了注解的应用程序。 不兼容性: 行为 - 工具:javac不再识别编译目标值1.4.1、1.4.2和jsr14
javac不再识别编译目标值
1.4.1
、1.4.2
和jsr14
,这些之前就没有记录在文档中。很多最新的代码生成惯用语中1.4.1
、1.4.2
比1.4
使用的更多,而组合选项-source 1.4 -target 1.5
会在更新一些的惯用语中使用,同时也会输出更新一些的字节码文件格式。”jsr14”选项则是泛型被添加到平台后的一个过度选项,现在泛型编译目标应该是1.5或更高。 不兼容性: 行为 RFE: 8010179 -
工具:javac类型转换编译问题 下面的代码在JDK 7中编译会出现警告,而在JDK 8中将无法编译:
import java.util.List; class SampleClass { static class Baz«span class=”hljs-title”>T> </span>{ public static List<Baz«span class=”hljs-built_in”>Object</span>» sampleMethod(Baz«span class=”hljs-built_in”>Object</span>> param) { return null; } } private static void bar(Baz arg) { Baz element = Baz.sampleMethod(arg).get(0); } }
JDK 8编译上面的代码中会报如下错误:
SampleClass.java:12: error:incompatible types: Object cannot be converted to Baz Baz element = Baz.sampleMethod(arg).get(0); Note: SampleClass.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 1 error
在这个例子中,原始类型被传递到
sampleMethod(Baz<Object>)
方法中,而这个方法应该传递的是其子类型(参考JLS,Java SE 7 Edition, 15.12.2.2章节)。如果要可用的话,就需要一个未经检查的转换,而他的返回类型是被擦除的(参考JLS,Java SE 7 Edition, 15.12.2.6章节)。在这个例子中,sampleMethod(Baz<Object>)
的返回类型是java.util.List
,而不是java.util.List<Baz<Object>>
,因此get(int)
的返回值是Object
,这就和被赋值的Baz类型不一致了。 更多的信息,请参见java.net上相关的电子邮件交流。 不兼容性: 源码 RFE: 7144506 - 工具:javac的final字段明确赋值问题
使用(译者注8u20已修复)this
关键字为final
字段明确的赋值分析。 传统的,Java语言禁止通过简单的名字(比如”x”)来访问没有明确赋值的final字段。在Java SE 7里,字段是可以通过”this.x”进行访问的(参见: https://bugs.openjdk.java.net/browse/JDK-7004835)。任何合法的程序在旧的规则下是非法的,而在新的规则下是不安全的,因为他必然会访问一个没有明确赋值的空白的final字段。 从JDK 8u20开始,javac编译器已经更新实现了Java SE 7的规则。 不兼容性: 源码 Bug: 8039026 -
工具:javac接口的实现进行编译时接口需要存在 当编译一个类,这个类中使用到的其中一个类实现了一个接口,而这个接口定义在别的文件中,这种类文件(定义接口的文件)在javac编译时必须可用。这是JDK 8的一个新的需求,不这样做会导致一个编译错误。例如: Client.java:
import p1.A; class Client { void test() { new A.m(); } }
p1/A.java:
package p1; public class A implements I { public void m() { } }
p1/I.java:
package p1; public interface I { void m(); }
如果p1/I.java或p1/I.class在编译Client.java时不可用,就会出现下面的错误信息:
Client.java: error: cannot access I new A().m(); ^ class file for p1.I not found
不兼容性: 行为
- XML:JAXP的Xalan扩展功能安全问题 JAXP中的Xalan扩展功能已经修改,以便于当SecurityManager存在时,默认的实现总是会被使用。这一改变会影响DOM Document创建的NodeSet。在之前,DOM实现由DOM工厂查找过程来定位。在这之后,当运行SecurityManager时,查找过程会跳过,并且用默认的DOM实现。 这个改变仅影响使用了第三方DOM实现的应用。一般来说,NodeSet结构预计与JDK默认实现相兼容。 不兼容性: 行为
- XML:JAXP1.6规范更新
JDK 8附带了JAXP 1.6,包括规范更新,要求使用
java.util.ServiceLoader
查找服务提供者。跨JAXP的服务提供者能够通过定义在java.util.ServiceLoader
的流程被一致的放置。而JDK7中提供者配置文件可以是位于不同地方的,例如,通过不同的类加载器的getXXX
方法比起ServiceLoader
,这个改变导致与JDK 7的细微的差异。 JDK 8 ships with JAXP 1.6 and so includes specification updates that mandate the use of java.util.ServiceLoader for finding service providers. Service providers across JAXP will now be located consistently following the process as defined in java.util.ServiceLoader. The changes may result in some subtle differences from implementations of JDK 7 where the provider-configuration file may have been located differently, for example, by using a different getXXX method of the ClassLoader than ServiceLoader. 应用实现自己的类加载器,应该确认类加载器的getXXX方式的实现是一致的,以便保持兼容性。 JSR 173中StAX API定义了接收factoryId
参数的newInstance
和newFactory
方法。因为在StAX规范中对这个参数没有任何限制,意味着可以是任意字符串。在JDK 8规范中进行了一下变更,在JAXP上下文里,如果他想要表示服务配置文件的名称,factoryId的值必须是基本服务类的名字,即,他不是一个系统属性名称。 不兼容性: 行为 RFE: 8005954 - XML:JAXP的javax.xml.stream工厂的类加载器不再忽略
在
javax.xml.stream
工厂中,类加载器参数不再能忽略。javax.xml.stream
包包含工厂类(XMLEventFactory、XMLOutputFactory、XMLInputFactory),这些工厂类定义newFactory方法时需要两个参数:factoryId和ClassLoader。在JDK 7中,第二个参数在查找和实例化服务时可以被省略。在JDK 8中不再能省略。可以参考这些方法的Java API文档来获取更详细信息。 不兼容性: 行为 RFE: 8005954
Java SE 8中移除的功能
- API:java.lang的Thread.stop关闭
Thread.stop
方法从JDK 1.2版本就被弃用了。这个方法现在会抛出一个UnsupportedOperationException。 - 核心库:java.net从需要的协议处理程序的列表中移除ftp协议
ftp是一个历史遗留的协议,它在很长时间内被一些更加安全的文件传输协议(比如
sftp
)取代。ftp
协议已经从协议处理程序列表中移除并且保证透明的。它实际上不是移除协议处理程序-应用使用这个协议时能够继续工作,但是它的存在已经不再需要。 RFE: 8000941 - 安全库:java.security不支持不安全的1024以下RSR密钥
在衡量基于加密算法的公钥强度上,秘钥的长度是一个很重要的安全参数。小于1024 bits的RSA秘钥被认为是可以破解的。
在这次更新中,如果他们的RSA秘钥长度小于1024 bits的话认证会被阻止。这个限制是通过Java Security property,
jdk.certpath.disabledAlgorithms
实施。这种做法会影响附着security property的provider(比如Sun provider和SunJSSE provider)。security property和jdk.certpath.disabledAlgorithms
也同样覆盖TLS使用的静态秘钥(X.509证书秘钥)的使用。 有了这些秘钥长度的限制,这些使用基于长度小于1024 bits的RSA秘钥的X.509证书在证书路径的建立和验证过程中会遇到兼容性的问题。这些秘钥的长度限制同样会影响需要验证X.509证书的JDK组件,比如JAR签名验证,SSL/TLS传输和HTTPS连接。 为了避免这些兼容性问题,使用了基于长度小于1024 bits的RSA秘钥的X.509证书的用户会被推荐使用更强的秘钥并更新他们的证书。作为一种变通的方法,在自己能够承受的风险之上,为了允许较小长度的秘钥,用户可以调节秘钥的长度来限制安全性(jdk.certpath.disabledAlgorithms
)。 不兼容性: 行为
JDK 8中移除的功能
Install:安装时不再提供关闭自动更新选项 为了关闭JRE的自动更新,关闭自动更新并且设置部署配置中的系统属性文件的deployment.expiration.check.enabled
属性为false
。为了关闭自动更新,移除Java控制面板中的更新按钮中的检测自动检测功能。查看Deployment Configuration File and Properties获取关于deployment.expiration.check.enabled property
的更多信息。Install:Solaris的Class Data Sharing文件不会被创建 在这之前,Solaris SVID包在安装时会创建Class Data Sharing文件。在JDK 8中,32位的Solaris不再被支持,因此Class Data Sharing文件也默认不会被创建。如果想要手动创建Class Data Sharing文件。执行下列命令:$JAVA_HOME/bin/java -Xshare:dump
当命令执行后,Class Data Sharing文件位于:$JAVA_HOME/jre/lib/server/{amd64,sparcv9}/classes.jsa
。 RFE: 8023498Deployment:Plugin移除经典的Java Plug-in 旧的Java Plug-in(Java SE 6u10之前的版本)会在这个版本中被移除。 RFE: 7076143Deployment:Plugin移除Java 快速开始(Java Quick Starter) Java快速开始(JQS)服务在这个版本中会被移除 RFE: 8004321Deployment:Plugin移除Active-X Bridge Active-X Bridge在这个版本会被移除。 RFE: 8004321- 核心库:sun.jdbc.odbc移除JDBC-ODBC Bridge 从JDK 8版本开始,JDK将不再包含JDBC-ODBC Bridge。JDBC-ODBC Bridge已经被认为是一个过渡期的产品,并且是一个仅仅用于选择JDK软件包并不包含在JRE中的JRE不支持的产品。可以使用数据库供应商提供或者是一个商业版本的JDBC Driver替换JDBC-ODBC Bridge。 RFE: 7176225
- Tools:apt移除apt工具
apt工具以及
com.sun.mirror
包中和它相关的API都将在这个版本中移除。使用命令行工具javac
以及包javax.annotation.processing
,包javax.lang.model
处理注解。 RFE: 7041249 Tools:java移除32位的Solaris 32位的Solaris操作系统的Java实现会在这个版本中移除。$JAVA_HOME/bin
和$JAVA_HOME/jre/bin
文件夹现在只包含64位的版本。为了过渡的目的,ISA(Instruction Specific Architecture)目录中$JAVA_HOME/bin/{sparcv9,amd64}
和$JAVA_HOME/jre/{sparcv9,amd64}
有指向32位版本的符号链接。这些ISA目录将在JDK 9版本中被移除。 SUNWj8rt,SUNWj8dev和SUNWj8dmo,这些之前包含32位版本的安装包现在包含64位版本。SUNWj8rtx,SUNWj8dvx和SUNWj8dmx安装包将被移除。 64位版本的java不会包含诸如Java Web Start和Java Plug-in的部署工具,因此桌面集成也不再需要了。 注意到64位的Solaris的可执行文件不能加载位32位Solaris编译和链接的JNI库。因此任何在32位Solaris系统中创建的JNI库都需要重新编译64位Solaris版本。 RFE: 8023288
Deprecated API
- 核心库:java.lang:class_loading弃用endorsed endorsed-standards override mechanism允许在Java Community Process维护的标准之外,或者是持续独立发展的作为Java SE平台的独立的APIs上实现新版本并且在运行时刻安装。 一个模块化的映像是由模块而不是jar包文件组成。往前看,我们希望通过可升级的模块(upgradeable module)只支持模块化形式的认可的标准和独立的APIs。 这个特性会在JDK 8u40版本中被弃用。这个弃用是为将来的Java SE版本中出现的module特性而做准备的。如果想要了解更多信息,查看JEP 200 - The Modular JDK和JEP 220 - Modular Run-Time Images。 这些改变不会改变运行时刻的行为。 RFE: 8065675
-
核心库:java.lang:class_loading弃用extension 扩展机制(extension mechanism)允许包含扩展了Java SE平台APIs的jar文件安装到一个运行时映像,使它们的内容在可见的情况下编译或运行的映像上的每一个应用程序。 这样的扩展机制在发布于1998年的JDK 1.2版本引入,但是在现在我们看不到任何凭证显示有人去使用这个特性。这并不奇怪,因为多数现代的Java应用程序会直接在class path上直接安装类库而不是在运行时刻去安装类库。 这个特性会在JDK 8u40版本时弃用。这个弃用是为将来的Java SE版本中出现的module特性而做准备的。如果想要了解更多信息,查看JEP 200 - The Modular JDK和JEP 220 - Modular Run-Time Images。 这个特性的弃用需要下列标准规范的改变:
- 在
java.lang.System.getProperties()
方法中,java.ext.dirs
系统属性的规范会被修订为包含一个会在将来版本中移除的弃用声明。 - 在
java.util.jar.Attributes.Name
类中,域EXTENSION_INSTALLATION
,IMPLEMENTATION_URL
和IMPLEMENTATION_VENDOR_ID
的被弃用表明应该使用class path代替它们。 -
在JAR文件的规范中,所有和打包JAR包的小程序依赖的已安装的可选包和触发对可选包下载的相关的manifest属性都被弃用。这些属性包括:
xtension-Name, Extension-List, <extension>-Extension-Name, <extension>-Specification-Version, <extension>-Implementation-Vendor-ID, <extension>-Implementation-Version, <extension>-Implementation-URL, Implementation-Vendor-Id, Implementation-URL,
和Extension-Installation
。 这些改变不会改变运行时刻的行为。 RFE: 8065702 - 核心库:java.lang弃用SecurityManager.checkMemberAccess
SecurityManager.checkMemberAccess
被弃用。它在调用者的栈帧深度为4的时候容易出错。JDK的实现将不再调用SecurityManager.checkMemberAccess
方法去执行成员变量访问控制的检测;替代它的是调用SecurityManager.checkPermission
方法。 通过重写checkMemberAccess
方法定制的SecurityManager
的实现可能会被影响导致重写的方法不会被调用。 - 核心库:java.lang弃用SecurityManager类的checkTopLevelWindow, checkSystemClipboardAccess, checkAwtEventQueueAccess
可替代的方法:
checkPermission
RFE: 8008981 - 核心库:java.rmi弃用RMI/JRMP的HTTP代理 RMI/JRMP的HTTP代理功能被弃用,而且HTTP的代理功能默认被关闭 RFE: 8023862
- 核心库:java.rmi弃用RMI(JRMP)静态生成stubs 不再支持RMI(JRMP)静态生成stubs RFE: 8023863
- 核心库:java.util.jar弃用Pack200.Unpacker接口的addPropertyChangeListener和removePropertyChangeListener
这些方法希望在将来的Java SE版本中移除
可替代的方法: 跟踪unpacker执行过程,轮询
PROGRESS
属性的值。 RFE: 8000362 - 核心库:java.util.logging弃用LogManager接口的addPropertyChangeListener和removePropertyChangeListener 这些方法希望在将来的Java SE版本中移除
- 核心库:com.sun.security.auth.callback弃用DialogCallbackHandler类 使用时会告知将会被移除,在JDK 9的版本中会被彻底移除。 RFE: 7190273
- 核心服务:javax.management的RMI连接器IIOP将移除 JSR-160规范已经更新了关于RMI连接器不再需要支持IIOP传输。Oracle JDK 8会继续支持IIOP的传输,但是支持IIOP的传输希望会在将来版本的JMX Remote API中移除。 RFE: 8001048
客户端库:javax.accessibility弃用javax.swing.JComponent.accessibleFocusHandler 可替代的方法:java.awt.Component.AccessibleAWTComponent.accessibleAWTFocusHandler
RFE: 7179482JavaFX:Scene Graph弃用Builder 可替代的方法: 使用合适的构造器和set方法去构造对象。 RFE: RT-30520- 安全库:java.security弃用insertProvider
java.security.SecurityPermission insertProvider.{provider name}
的目标名称在将来使用时会被劝阻,因为他可能在重写java.security.Provider.getName
方法时会遇到命名约束而被阻止。同样,在使用通过插入一个指定命名或者是选择获取的任意名称的provider授予代码权限时会有同样的风险。 可替代的方法: 新的insertProvider
目标名称。兼容现有已经被保留的policy文件,原因在于新旧的权限都会被Security.addProvider
和insertProviderAt
方法检测。 RFE: 8001319 * -
HotSpot JVM:gc弃用一些组合 以下的GC组合被弃用:
- DefNew + CMS
- ParNew + SerialOld
-
Incremental CMS 对应的命令行选项会产生警告信息并且建议你不要使用这样的组合。这些命令行选项会在将来的某个主要版本中移除。
- 命令行选项
-Xinggc
被弃用 - 命令行选项
-XX:CMSIncrementalMode
被弃用。注意,这个命令行选项会影响所有的CMSIncremental
选项。 - 命令行选项
-XX:+UseParNewGC
被弃用。除非你同时使用选项-XX:+UseConcMarkSweepGC
。 - 命令行选项
-XX:-UseParNewGC
只有在和-XX:+UseConcMarkSweepGC
选项一起使用时被弃用。 想要获得更多的信息,请查看 http://openjdk.java.net/jeps/173 RFE:8006479
- Hotspot:gc弃用CMS GC的前端收集器
CMS GC的前端收集器(foreground collector)已经被弃用,并且希望在将来的某个版本中移除。使用G1或者是常规的CMS替代。
比如在使用
-XX:+UseCMSCompactAtFullCollection -XX:+CMSFullGCsBeforeCompaction -XX:+UseCMSCollectionPassing
等选项时,会打印一个已经弃用的警告,但是VM仍会继续工作。 RFE: 8027132