插入USB热点后,简单Java程序速度慢100倍

插入USB热点后,简单Java程序速度慢100倍,java,windows,performance,networking,windows-7,Java,Windows,Performance,Networking,Windows 7,我有以下Java程序: 主类{ 公共静态void main(字符串[]args)引发java.io.IOException{ 长启动=System.nanoTime(); createTempFile(“java_test”,“.txt”).delete(); System.out.println((System.nanoTime()-start)/1e9); } } 通常,执行大约需要63毫秒: $javamain 0.06308555 但是,一旦我把安卓手机连接成USB热点,就要花更长的

我有以下Java程序:

主类{
公共静态void main(字符串[]args)引发java.io.IOException{
长启动=System.nanoTime();
createTempFile(“java_test”,“.txt”).delete();
System.out.println((System.nanoTime()-start)/1e9);
}
}
通常,执行大约需要63毫秒:

$javamain
0.06308555
但是,一旦我把安卓手机连接成USB热点,就要花更长的时间。根据机器的不同,在3到40秒内:

$javamain
4.263285528
奇怪的是,这里没有任何东西是通过网络传输的——插入式网络适配器应该无关紧要

我做了回溯,看起来大部分时间都花在
NetworkInterface上。getAll
方法:

“main”#1优先级=5 os_优先级=0 tid=0x00000000023ae000 nid=0x142c可运行[0x000000000268d000]
java.lang.Thread.State:可运行
位于java.net.NetworkInterface.getAll(本机方法)
位于java.net.NetworkInterface.getNetworkInterfaces(未知源)
位于sun.security.provider.SeedGenerator.addNetworkAdapterInfo(未知源)
位于sun.security.provider.SeedGenerator.access$000(未知来源)
位于sun.security.provider.SeedGenerator$1.run(未知源)
位于sun.security.provider.SeedGenerator$1.run(未知源)
位于java.security.AccessController.doPrivileged(本机方法)
位于sun.security.provider.SeedGenerator.getSystemEntropy(未知源)
位于sun.security.provider.SecureRandom$SeederHolder。(未知来源)
位于sun.security.provider.SecureRandom.engineNextBytes(未知源)
-锁定(sun.security.provider.SecureRandom)
位于java.security.SecureRandom.nextBytes(未知源)
-锁定(一个java.security.SecureRandom)
位于java.security.SecureRandom.next(未知源)
位于java.util.Random.nextLong(未知源)
位于java.io.File$TempDirectory.generateFile(未知源)
位于java.io.File.createTempFile(未知源)
位于java.io.File.createTempFile(未知源)
Main.Main(Main.java:4)
而这又似乎将大部分时间花在了
GetIfTable
Windows API方法上:

子SP重新寻址呼叫站点
00000000`0257ed78 000007fe`fd7210ba ntdll!NtDeviceIoControlFile+0xa
00000000`0257ed80 000007fe`fd721252 nsi+0x10ba
00000000`0257ee20 000007fe`fd7211f9 nsi!NSIEmpareObjectsAllParameterSex+0x2e
00000000`0257ee60 000007fe`fd7217b0 nsi!NSI枚举对象参数+0xc9
00000000`0257ef00 000007fe`f9c7928d nsi!nsialocateAndGetTable+0x184
00000000`0257EFD000000000`6f8c5a01 IPHLAPI!GetIfTable+0xa9
00000000`0257f090 00000000`6f8c6980净值!Java\u Java\u网络\u网络接口\u getMTU0+0x1a1
00000000`0257f150 00000000`6f8c6e57净值!Java\u Java\u网络\u网络接口\u isP2P0\u XP+0x88
00000000`0257f270 00000000`6f8c6058净值!Java\u Java\u网络\u网络接口\u getAll\u XP+0x23
00000000`0257F2A000000000`02867f54净值!Java\u Java\u网络\u网络接口\u getAll+0x2c
GetIfTable
似乎是有问题的函数。我在示例程序中观察到了相同的减速:和以下代码片段:

#包括
#包括
int main(){
DWORD dwSize=sizeof(MIB_IFTABLE);
MIB_IFTABLE*pifttable=malloc(dwSize);
GetIfTable(pIfTable和dwSize,FALSE);
pIfTable=malloc(dwSize);
GetIfTable(pIfTable和dwSize,FALSE);
返回0;
}
如何修复或解决此问题? 我可以自己创建临时文件,并避免调用NetworkInterface.getNetworkInterfaces,但SecureRandom在Java标准库中广泛使用。 有没有办法强制SecureRandom不使用GetIfTable

Java版本:

>java-version
java版本“1.8.0_101”
Java(TM)SE运行时环境(build 1.8.0_101-b13)
Java HotSpot(TM)64位服务器虚拟机(构建25.101-b13,混合模式)
Windows版本:

操作系统名称:Microsoft Windows 7 Professional 操作系统版本:6.1.7601 Service Pack 1 Build 7601 有问题的网络适配器:

Name[00000020]基于NDIS的远程互联网共享设备
适配器类型以太网802.3
基于NDIS的产品类型远程互联网共享设备
是的
PNP设备ID USB\VID\u 0FCE&PID\u 71C4&MI\u 00\7&6BE3F3B&0&0000
最后一次重置2016年8月14日下午12:26
索引20
服务名称usb\u rndisx
IP地址192.168.42.183,fe80::90ab:3786:4396:2870
IP子网255.255.255.0,64
默认IP网关192.168.42.129
已启用DHCP是
DHCP服务器192.168.42.129
DHCP租约将于2016年8月14日下午3:27到期
DHCP租约于2016年8月14日下午2:27获得
MAC地址02:18:61:77:7D:72
驱动程序c:\windows\system32\drivers\usb8023x.sys(6.1.7600.16385,19.50KB(19968字节),2009年7月14日凌晨2:09)

作为系统熵的额外来源的
SecureRandom
的默认实现。为了避免这种情况,您需要注册一个包含不同实现的自定义

幸运的是,JDK for Windows已经有了一个合适的
SecureRandomSpi
实现,它依赖于Microsoft Crypto API:。尽管这是一个非公共API,但该类存在于OpenJDK和Oracle JDK的所有版本(从1.6到9)中,并且回退仍然可用

有两种方法可以将MS Crypto PRNG注册为默认的SecureRandom算法

1。从应用程序内部调用
WindowsSecureRandom.register()

import java.security.Provider;
import java.security.Security;

public class WindowsSecureRandom extends Provider {
    private static final String MSCAPI = "sun.security.mscapi.PRNG";

    private WindowsSecureRandom() {
        super("WindowsSecureRandom Provider", 1.0, null);
        putService(new Service(this, "SecureRandom", "Windows-PRNG", MSCAPI, null, null));
    }

    public static void register() {
        if (System.getProperty("os.name").contains("Windows")) {
            try {
                Class.forName(MSCAPI);
                Security.insertProviderAt(new WindowsSecureRandom(), 1);
            } catch (ClassNotFoundException e) {
                // Fallback to default implementation
            }
        }
    }
}
2.通过对
%JAVA\u HOME%\jre\lib\security\JAVA.security
文件中的提供程序列表重新排序

security.provider.1=sun.security.mscapi.SunMSCAPI  <<<--- make it the first provider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=sun.security.ec.SunEC
security.provider.5=com.sun.net.ssl.internal.ssl.Provider
...

security.provider.1=sun.security.mscapi.sunmcscapi看起来这样可以。我有点担心这样滥用非API。@Banthar我找到了另一个更干净的解决方案,它不需要补丁