JJWT默认SecureRandom为何有时阻塞有时不?是否与熵池有关?
你的疑惑核心是对的:这个现象确实和系统熵池的状态直接相关,具体可以从这几个角度拆解:
NativePRNG的阻塞触发逻辑
JJWT默认用的NativePRNG实现,其阻塞行为完全依赖系统熵池的充足程度:当系统熵池(用于生成加密安全随机数的“随机种子”来源)不足时,它会同步读取/dev/random(类Unix系统)这类阻塞型熵源,此时就会被BlockHound检测到阻塞调用;而当系统熵池充足时,它会直接从已积累的熵池中取数据,不会触发阻塞操作,自然不会被BlockHound告警。SecureRandom实例的复用特性
JJWT内部会复用SecureRandom实例,而非每次生成JWT ID都新建实例。如果你之前切换到NativePRNGNonBlocking的操作已经让JVM初始化了一个可用的随机数实例,或者系统运行一段时间后熵池已经积累足够,后续复用旧代码时,这个已初始化的实例会直接使用充足的熵源,不会再触发阻塞读取。BlockHound的检测逻辑
BlockHound只检测实际发生的阻塞调用,而非静态代码路径。只有当SecureRandom真的进入阻塞读取熵池的分支时,才会抛出告警。如果系统熵池足够,NativePRNG的调用全程是非阻塞的,BlockHound就不会捕捉到异常。
验证方法
你可以手动耗尽系统熵池(比如在类Unix系统执行cat /dev/random > /dev/null,直到命令卡住),然后再运行旧代码,此时应该会再次触发BlockHound的阻塞检测,就能确认熵池状态是核心原因。
内容的提问来源于stack exchange,提问作者suw0n

