JxtaMulticastSocket覆写了java.net.MulticastSocket的bind方法:

@Override
public void bind(SocketAddress addr) throws SocketException {
if (isBound()) {
throw new SocketException("Already bound");
}
}
 
要求在JxtaMulticastSocket的构造函数中会调用bind方法,确保构造函数调用时socket没有被绑定,否则抛出SocketException异常
然而JxtaMulticastSocket的基类java.net.MulticastSocket的构造函数在jdk7和jdk8中的处理是不同的
 
jdk7:

    public MulticastSocket(SocketAddress bindaddr) throws IOException {
super((SocketAddress) null); // Enable SO_REUSEADDR before binding
setReuseAddress(true); if (bindaddr != null) {
bind(bindaddr);
}
}

jdk8:

    public MulticastSocket(SocketAddress bindaddr) throws IOException {
super((SocketAddress) null); // Enable SO_REUSEADDR before binding
setReuseAddress(true); if (bindaddr != null) {
try {
bind(bindaddr);
} finally {
if (!isBound())
close();
}
}
}
可见在jdk8中,如果未绑定,会额外调用close()方法,就是这个close()方法导致抛出了异常
其实在这里不能调用close()方法,从代码上看JxtaMulticastSocket在实现的时候要求此时不能绑定(见其覆写的bind方法)
而close方法也被JxtaMulticastSocket覆写了

/**
* Closes this MutlicastSocket.
*/
@Override
public synchronized void close() {
if (closed) {
return;
}
bound = false;
closed = true;
in.close();
outputPipe.close();
in = null;
}

此时in尚未初始化,故in.close()会导致java.lang.NullPointerException异常

————————————

1 简单的话,可以修改JxtaMulticastSocket的构造函数,使其不再调用父类的构造函数以避免close()问题(父类构造函数中的相关代码要在子类中重新实现一遍)。
2 或者不修改JxtaMulticastSocket的源码,我们干脆自己实现一个子类,提供自己的构造函数初始化代码。

3 较好的方式那就要全面考虑JxtaMulticastSocket的实现了,那就比较复杂了

————————————————————————

。。。

1和2现在看起来不大现实,因为父类java.net.MulticastSocket最终都调用了如下构造方法:

    /**
* Create a MulticastSocket bound to the specified socket address.
* <p>
* Or, if the address is {@code null}, create an unbound socket.
*
* <p>If there is a security manager,
* its {@code checkListen} method is first called
* with the SocketAddress port as its argument to ensure the operation is allowed.
* This could result in a SecurityException.
* <p>
* When the socket is created the
* {@link DatagramSocket#setReuseAddress(boolean)} method is
* called to enable the SO_REUSEADDR socket option.
*
* @param bindaddr Socket address to bind to, or {@code null} for
* an unbound socket.
* @exception IOException if an I/O exception occurs
* while creating the MulticastSocket
* @exception SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @see SecurityManager#checkListen
* @see java.net.DatagramSocket#setReuseAddress(boolean)
*
* @since 1.4
*/
public MulticastSocket(SocketAddress bindaddr) throws IOException {
super((SocketAddress) null); // Enable SO_REUSEADDR before binding
setReuseAddress(true); if (bindaddr != null) {
try {
bind(bindaddr);
} finally {
if (!isBound())
close();
}
}
}

这意味着子类无论直接还是间接,最终都要调用到这个方法,故close()难以避免的啊!

那就只有修改JxtaMulticastSocket覆写的close()方法了,原close()方法:

    /**
* Closes this MutlicastSocket.
*/
@Override
public synchronized void close() {
if (closed) {
return;
}
bound = false;
closed = true;
in.close();
outputPipe.close();
in = null;
}

修改后:如果尚未绑定的话,close()不执行任何操作

    /**
* Closes this MutlicastSocket.
*/
@Override
public synchronized void close() {
// modified by cuizhf, 20131126
// @see http://www.cnblogs.com/cuizhf/admin/EditPosts.aspx?postid=3443599
if(!bound) {
return;
}
if (closed) {
return;
}
bound = false;
closed = true;
in.close();
outputPipe.close();
in = null;
}

或者这样写:

    /**
* Closes this MutlicastSocket.
*/
@Override
public synchronized void close() {
// modified by cuizhf, 20131126
// @see http://www.cnblogs.com/cuizhf/admin/EditPosts.aspx?postid=3443599
if (!bound || closed) {
return;
}
bound = false;
closed = true;
in.close();
outputPipe.close();
in = null;
}

虽然不是很优雅,至少应该能解决眼前的问题。(实话说Jxse的代码确实算不上优雅)

————————————————————————————————————————————————————————

另外一种修改方式就是将java.net.MulticastSocket单独从JDK中提出到在自己的工程中,然后按自己的需要修改(在构造函数中去掉close()的调用),最后使JxtaMulticastSocket继承自修改后的这个类。

 
 
 
 —————————————————————————————————————————————————————————
好吧,从今天开始,secondegg项目的开发全面转向JDK8(JavaFX8)。

jxse2.6在jdk8下,JxtaMulticastSocket存在的问题的更多相关文章

  1. JDK8下的HashMap有什么特别之处?

    一.前言 上篇认真的分析了在JDK7下的HashMap, 如果还没看过的或者忘记了的可以先去回顾下,这样可以更好的了解JDK8下的HashMap基于JDK7做了什么改动.分析JDK8下的HashMap ...

  2. JVM源码分析之JDK8下的僵尸(无法回收)类加载器[z]

    [z]http://lovestblog.cn/blog/2016/04/24/classloader-unload/ 概述 这篇文章基于最近在排查的一个问题,花了我们团队不少时间来排查这个问题,现象 ...

  3. JDK8下Object类源码理解

    JDK8中Object类提供的方法: package java.lang; /** * Class {@code Object} is the root of the class hierarchy. ...

  4. jdk8下的接口和抽象类

    接口 在java8中,接口可以定义变量和方法,其中变量必须为 public && static && final: 方法必须为public && (ab ...

  5. dubbo-admin在jdk8下不兼容

    参考这里 修改pom.xml webx的依赖改为3..6版 <dependency> <groupId>com.alibaba.citrus</groupId> & ...

  6. JDK8下maven使用maven-javadoc-plugin插件报错

    由于JDK8的doc生成机制比之前的要严谨许多,导致项目用maven打包的时候出错 解决办法: 添加-Xdoclint:none配置 完整配置如下:   <plugin> <grou ...

  7. jdk8下面的ArrayList的扩容

    一. ArrayList class ArrayList<E> extends AbstractList<E> implements List<E>, Random ...

  8. xp下安装jdk8

    下载jdk8安装包,地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html下载7- ...

  9. 高性能场景下,HashMap的优化使用建议

    1. HashMap 在JDK 7 与 JDK8 下的差别 顺便理一下HashMap.get(Object key)的几个关键步骤,作为后面讨论的基础. 1.1 获取key的HashCode并二次加工 ...

随机推荐

  1. 二、理解over()函数

    1.1.两个order by的执行时机分析函数是在整个sql查询结束后(sql语句中的order by的执行比较特殊)再进行的操作, 也就是说sql语句中的order by也会影响分析函数的执行结果: ...

  2. mysql中sql语句执行时间

    delimiter // set @d=now(); select * from comment; select timestampdiff(second,@d,now()); delimiter ; ...

  3. HDU 1394 (逆序数) Minimum Inversion Number

    原来求逆序数还可以用线段树,涨姿势了. 首先求出原始序列的逆序数,然后递推每一个序列的逆序数. #include <cstdio> #include <cstring> #in ...

  4. myeclipes准备工作

    设置jsp中默认编码为utf-8

  5. BZOJ 4552 排序

    省选TM都能有BC原题? ... #include<iostream> #include<cstdio> #include<cstring> #include< ...

  6. 使用过的Linux命令

    1 在vim中编辑python,由于tab是8个空格,然而python中是4个,需要替换 :%s/\t/    /g 2 tar tar -czvf topic_dt_poi.0801.0818.ta ...

  7. swun 1766 我的悲剧不可能那么好数

    解题思路: 一向提交特别慎重的我,这题竟然PE了5发左右,放了几天,再回来写,直接1A, 相当的自豪,而且是最优解题者.这题千万要注意,化繁为简,文章只包括大小   写字母和数字,还有空行. #inc ...

  8. 【UVa-514】铁轨——栈的学习

    UVa514 Rails(铁轨) 题目:铁轨 题目链接: UVa514链接 题目描述: 某城市有一个火车站,有n节车厢从A方向驶入车站,按进站的顺序编号为1-n.你的任务是判断是否能让它们按照某种特定 ...

  9. Hbase shell详情

    HBase 为用户提供了一个非常方便的使用方式, 我们称之为“HBase Shell”.HBase Shell 提供了大多数的 HBase 命令, 通过 HBase Shell 用户可以方便地创建.删 ...

  10. sed命令使用记录

    背景:文件A,文件B,文件格式一致,有两列,第一列为key,第二列为value. 目的:将文件A中的内容插入到文件B中,不能在最后,不能有重复key(我的key和value用tab键分割) 实现:我的 ...