Lea*_*par 7 java ssl multithreading
在我的测试中,我能够毫无问题地使用它们,但我找不到文档说明SSLSocketFactory.createSocket()是否是线程安全的.可以在多个线程中使用相同的SSLSocketFactory来创建SSL套接字吗?
我的应用程序使用一个处理将纯文本套接字升级到SSL的类:
public class SSLHandler() {
public Socket upgradeToSSL(Socket plainSocket) {
SSLSocket sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManager = new TrustManager[]{
new MyOwnTrustManager()
};
sslContext.init(null, trustManager, null);
SSLSocketFactory sslsocketfactory = sslContext.getSocketFactory();
sslSocket = (SSLSocket) sslsocketfactory.createSocket(
remoteSocket,
remoteSocket.getInetAddress().getHostAddress(),
remoteSocket.getPort(),
true);
return sslSocket;
}
}
Run Code Online (Sandbox Code Playgroud)
SSLHandler类用于多个线程,如下所示:
Socket plainSocket = new Socket(host, port);
//Do some stuff in plain text...
//Lets use TLS now
SSLHandler sslHandler = new SSLHandler();
sslHandler.upgradeToSSL(Socket plainSocket);
plainSocket = upgradeToSSL(plainSocket);
Run Code Online (Sandbox Code Playgroud)
因此,对于每个新线程,都会创建一个SSLHandler.为了避免这种情况,我正在考虑使用Singleton模式重构SSLHandler:
public class SingletonSSLHandler() {
private SSLSocket sslContext;
private SSLSocketFactory sslSocketFactory;
//GetInstance() and etc.
private SingletonSSLHandler() {
sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManager = new TrustManager[]{
new MyOwnTrustManager()
};
sslContext.init(null, trustManager, null);
sslSocketFactory = sslContext.getSocketFactory();
}
public static Socket upgradeToSSL(Socket plainSocket) {
sslSocket = (SSLSocket) sslsocketfactory.createSocket(
remoteSocket,
remoteSocket.getInetAddress().getHostAddress(),
remoteSocket.getPort(),
true);
return sslSocket;
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题可没那么容易回答。原因是有执行,也有合同层面。
执行
SSLServerSocketFactory 类是抽象的,并且具有插件扩展机制。因此,从理论的角度来看,您无法确定您正在实施什么。
默认实现只是一个虚拟实现,由 JVM 选择的提供者的实现实例进行交换:
//
// The default factory does NOTHING.
//
class DefaultSSLServerSocketFactory extends SSLServerSocketFactory {
...
}
Run Code Online (Sandbox Code Playgroud)
抽象类中有一些同步的迹象。为了给出 JDK 中实现的答案,需要针对每个操作系统(Windows、Linux、Mac OS)上的每个 JDK 版本来分析该问题。
当您进入下一节中的合同级别时,关键部分(同步)的存在毫无意义。从我的角度来看,合同级别是本次讨论中最重要的。
合同
事实上,如果没有 API 文档保证/承诺它是线程安全的。所以,理论上来说不是。您不能依赖任何没有 API 合同的东西。请阅读Josh Bloch 的“黄金法则 70:记录线程安全”,以获取有关依赖线程安全的假设的非常详细的讨论。
我可以使用上面提到的扩展机制编写一个非线程安全的 SSLServerSocketFactory 实现。缺乏线程安全不会是一个错误,因为它不是每个接口契约所强制的。
概括
总而言之,API 并不保证所有实现都是线程安全的。所以没有办法说会有一个(未来的)实现不是线程安全的。