java:解决URL.setURLStreamHandlerFactory只能被jvm调用一次的问题

如果你能找到这篇博客,你肯定是为实现URL协议扩展时自定义协议的StreamHandlerFactory注册问题而头痛。 一般而言,URL 的格式是: protocol://[authority]hostname:port/resource?queryString 常见协议头(protocol)有http,https,file。对应不同的协议,java都有提供默认URLStreamHandler对象来解析这些协议,如下图,这些位于rt.jar包中每一个package都对应一种协议,package下都有一个继承自URLStreamHandler的Handler类用于对应协议解析

如果要实现自己的协议,就需要自己写一个URLStreamHandler,如何写URLStreamHandler与具体项目需求相关,不是本文要讨论的重点。当我们想让自己写的URLStreamHandler生效,就需要将它注册到URL中,这篇文章《Java URL协议扩展实现》详细描述了两种机制,来实现URL协议扩展。 第一种方法就是用URL.setURLStreamHandlerFactory方法将自己的URLStreamHandlerFactory注册到URL类中。我打算采用的就是这种方式,因为这种方式相比jvm参数方式更加可控。 然而,根据URL.setURLStreamHandlerFactory方法的说明以及其代码可知,这个方法具有独占性,在JVM运行时只能被调用一次。(现在看来,这应该算是java的一个设计缺陷) 一般情况下,我们不一定能保证在自己调用URL.setURLStreamHandlerFactory时是第一次,所以调用很有可能失败。 怎么解决这个问题呢?Apache Commons Sandbox提供了一个解决方法,就是commons-jnet,它基本原理就是使用java reflect技术,强行改变URL中的私有成员变量factory(类型为URLStreamHandlerFactory)来保setURLStreamHandlerFactory能被成功调用,并且不破坏原有的factory。 common-jnet代码非常少,只有4个类,没有提供jar包,只是提供源码,从svn上checkout出来加入自己的项目代码就可以使用了

svn checkout http://svn.apache.org/repos/asf/commons/sandbox/jnet/trunk commons-jnet

具体的使用方式,common-jnet的官网上说明得非常明白也非常简单。 http://commons.apache.org/sandbox/commons-jnet/

找到common-jnet之前就发现org.eclipse.osgi中的EquinoxFactoryManager就是用相同的办法解决这个问题的,只是其中的代码混在一起不好摘出来。

参见 EquinoxFactoryManager.installURLStreamHandlerFactory方法和 EquinoxFactoryManager.forceURLStreamHandlerFactory方法的源码

参考资料:

《Java URL协议扩展实现》 apache.sandbox.commons-jnet

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我的博客

PHPUnit使用笔记

1.引入composer composer require  phpunit/phpunit 2.编写测试代码 <?php require_once './v...

37517
来自专栏哲学驱动设计

C# async/await 使用总结

今天搞这两个关键字搞得有点晕,主要还是没有彻底理解其中的原理。 混淆了一个调用异步方法的概念: 在调用异步方法时,虽然方法返回一个 Task,但是其中的代码已经...

1826
来自专栏张善友的专栏

利用Windows性能计数器(PerformanceCounter)监控

一、概述 性能监视,是Windows NT提供的一种系统功能。Windows NT一直以来总是集成了性能监视工具,它提供有关操作系统当前运行状况的信息,针对各种...

2189
来自专栏北京马哥教育

Linux下高并发Socket连接的优化

1、打开文件优化 #对当前shell ulimit -n 102400 echo “ulimit -n 102400″ >> ~/.bashrc #针对所有用户...

2678
来自专栏惨绿少年

linux进程资源占用高原因分析命令记录

1、查看进程的线程: ps -eLf|egrep 'gateserver|UID' 2、跟踪线程调用: strace -p 15530 3、统计线程中函数的调用...

1720
来自专栏微服务生态

为什么说Kafka使用磁盘比内存快

学习过[跟我学Kafka源码之LogManager分析]的同学一定会问为什么Kafka大量使用了磁盘作为传统意义的缓存。

652
来自专栏转载gongluck的CSDN博客

UNPv13:#第5章#TCP客户/服务器程序示例

Code github //server.c #include <unistd.h> #include <stdio.h> #include <stdlib....

3245
来自专栏禁心尽力

解决springmvc在单纯返回一个字符串对象时所出现的乱码情况(极速版)

使用springmvc框架开发了这么长时间,之前都是直接返回jsp页面,乱码情况都是通过配置和手动编解码来解决,但是今天突然返回一段单纯的字符串时,发现中文乱码...

1819
来自专栏计算机视觉与深度学习基础

Leetcode 202 Happy Number

Write an algorithm to determine if a number is "happy". A happy number is a nu...

1839
来自专栏DT乱“码”

POST中文乱码解决方案

POST中文乱码解决方案 ? Spring Web MVC提供了Filter用于解决POST方式造成的中文乱码问题,具体配置 如下: <filter> ...

1905

扫码关注云+社区