Java SecureRandom的一点记录

本文探讨了Java中SecureRandom类在Linux环境下可能导致线程阻塞的问题。具体介绍了SecureRandom的工作原理,不同操作系统下的默认算法,以及如何通过配置避免性能瓶颈。
先记录一下两个帖子的地址:
1. [url=https://www.cigital.com/blog/proper-use-of-javas-securerandom/]Proper Use Of Java SecureRandom[/url]
2. [url=https://tersesystems.com/2015/12/17/the-right-way-to-use-securerandom/]The Right Way to Use SecureRandom[/url]

JDK版本: 1.8.0_66

事情的起因还是 SecureRandom.generateSeed()在Linux系统上卡住导致线程block这个现象。见讨论:
http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom

事实上,如果使用SecureRandom.getInstanceStrong()这种方法初始化SecureRandom对象的话,也会在Linux上产生类似问题。

记录一下知识点(这玩意儿其实挺冷门的):
1.SecureRandom本身并不是伪随机算法的实现,而是使用了其他类提供的算法来获取伪随机数。

2.如果简单的new一个SecureRandom对象的话,在不同的操作平台会获取到不同的算法,windows默认是SHA1PRNG,Linux的话是NativePRNG。

3. Linux下的NativePRNG,如果调用generateSeed()方法,这个方法会读取Linux系统的/dev/random文件,这个文件在JAVA_HOME/jre/lib/securiy/java.security里面有默认定义。而/dev/random文件是动态生成的,如果没有数据,就会阻塞(后面这句结论阻塞正确,至于为什么阻塞没细看)。也就造成了第一个现象。

4.可以使用-Djava.security.egd=file:/dev/./urandom (这个文件名多个u)强制使用/dev/urandom这个文件,避免阻塞现象。中间加个点的解释是因为某个JDK BUG,SO那个帖子有链接。

5.如果使用SecureRandom.getInstanceStrong()这种方法初始化SecureRandom对象的话,会使用NativePRNGBlocking这个算法,而NativePRNGBlocking算法的特性如下:
NativePRNGBlocking uses /dev/random for all of the following operations:
Initial seeding: This initializes an internal SHA1PRNG instance using 20 bytes from /dev/random
Calls to nextBytes(), nextInt(), etc.: This provides the XOR of the output from the internal SHA1PRNG instance (see above) and data read from /dev/random
Calls to getSeed(): This provides data read from /dev/random

可见这个算法完全依赖/dev/random,所以当这个文件随机数不够的时候,自然会导致卡顿了。
6.如果使用NativePRNGBlocking算法的话,4中的系统参数失效!!!(这个是从http://hongjiang.info/java8-nativeprng-blocking/看到的)
7.一般使用SecureRandom不需要设置Seed,不需要设置算法,使用默认的,甚至一个静态的即可,如果有需求的话可以在运行一段时间后setSeed一下。(这点是自己总结的)
<think>嗯,用户问的是如何编写详细的代码注释,需要示例最佳实践。让我先回忆一下相关的引用内容。用户提供了三个引用,都是关于代码注释的重要性最佳实践的。引用1提到好的注释能增加可读性、协作维护,引用2强调清晰明了、及时更新避免冗余,引用3则建议内联注释用于解释复杂部分。 首先,我需要整理这些要点,然后结合示例来说明。用户可能希望具体的例子,比如函数注释、复杂逻辑的注释等。需要分步骤回答,结构清晰,比如按注释类型分类,每个类型给出示例最佳实践。 还要注意用户提到的系统级指令,比如数学公式要用$...$,不过这里的问题是关于代码注释,可能用不上数学公式,但得确保其他格式正确。比如代码块需要用反引号包裹,单独成段。 可能用户是开发人员,尤其是团队协作中的开发者,他们需要提高代码的可维护性。深层需求可能是希望代码更易理解,减少沟通成本,或者在维护时更容易定位问题。 接下来,我需要将引用中的建议整合到回答中。比如引用2提到的及时更新注释,避免冗余,使用文档注释。引用3的内联注释的例子。这些都可以作为不同部分的例子。 然后,结构方面,可能分为注释类型、示例、最佳实践、常见误区。每个部分用标题,然后给出具体内容。确保每个建议都有对应的引用标注,比如[^1][^2][^3]。 需要检查是否有遗漏的最佳实践,比如是否需要提到工具生成文档,或者注释风格的一致性。引用2提到了Javadoc,所以可以包含在文档注释部分。 最后,相关问题部分要生成三个相关问题,可能涉及注释工具、维护策略、自动化生成等。要确保问题相关且有价值,帮助用户进一步探索。</think>### 如何编写详细的代码注释:示例与最佳实践 代码注释是提升代码可维护性协作效率的关键工具。以下是分步指南具体示例: --- #### 一、注释的三大类型及示例 1. **文档注释(描述整体功能)** ```python def calculate_interest(principal, rate, time): """ 计算复利利息(基于年利率) Args: principal (float): 本金 rate (float): 年利率(如5%输入为0.05) time (int): 投资年限 Returns: float: 总金额(本金+利息) Raises: ValueError: 当输入参数为负数时触发 """ if principal < 0 or rate < 0 or time < 0: raise ValueError("参数必须为非负数") return principal * (1 + rate) ** time ``` **最佳实践** - 使用标准格式(如Python的docstring、JavaJavadoc)[^2] - 明确参数类型、返回值异常情况 2. **逻辑注释(解释复杂算法)** ```javascript // 使用快速选择算法查找第k小元素(时间复杂度O(n)) function quickSelect(arr, k) { // 递归终止条件:数组长度为1时直接返回 if (arr.length === 1) return arr[0]; // 随机选择基准元素避免最坏情况 const pivot = arr[Math.floor(Math.random() * arr.length)]; // 分区操作:小于、等于、大于基准值的三个数组 const lows = arr.filter(x => x < pivot); const highs = arr.filter(x => x > pivot); const pivots = arr.filter(x => x === pivot); // 根据k值所在区间递归处理 if (k < lows.length) return quickSelect(lows, k); else if (k < lows.length + pivots.length) return pivots[0]; else return quickSelect(highs, k - lows.length - pivots.length); } ``` **最佳实践** - 解释算法选择复杂度(如快速选择算法的时间复杂度) - 标注关键步骤的意图而非重复代码[^3] 3. **内联注释(澄清易混淆细节)** ```cpp void processImage(Image& img) { // 将图像从BGR转为RGB格式(OpenCV默认使用BGR) cvtColor(img, img, COLOR_BGR2RGB); // 添加高斯模糊(σ=1.5)以降低高频噪声 GaussianBlur(img, img, Size(5,5), 1.5); } ``` **最佳实践** - 说明参数选择依据(如σ=1.5的物理意义) - 标注第三方库的特殊行为(如OpenCV颜色空间)[^3] --- #### 二、注释的黄金准则 1. **可操作性原则** ```python # 错误示例:冗余注释 x = x + 1 # 将x增加1 # 正确示例:解释业务逻辑 # 用户连续登录失败5次后锁定账户(安全策略第3章) if login_attempts >= 5: lock_account() ``` 2. **同步更新机制** - 在代码审查清单中加入"注释与代码同步检查"[^2] - 使用IDE插件自动检测过时注释(如VS Code的Todo Tree) 3. **分层注释策略** ```java /** * 实现JWT令牌生成(RFC 7519标准) * 包含HS256签名30分钟过期时间 */ public class JwtGenerator { // 使用线程安全的SecureRandom生成盐值 private static final SecureRandom secureRandom = new SecureRandom(); public String generateToken(User user) { // 避免敏感信息泄漏:payload仅包含userId角色 Map<String, Object> claims = new HashMap<>(); claims.put("userId", user.getId()); claims.put("role", user.getRole()); // 代码继续... } } ``` --- #### 三、注释的典型误区 | 错误类型 | 反例 | 改进方案 | |---------|------|---------| | 幽灵注释 | `// 这里需要优化` | `// 优化点:数据库查询未使用索引(见ISSUE-45)` | | 故事注释 | `// 张三在2020年添加了这个补丁` | 使用版本控制系统记录修改历史 | | 过度注释 | 每行代码都添加解释 | 仅在关键逻辑点注释 | --- #### 四、工具链推荐 1. **文档生成**:Doxygen(C++)、Sphinx(Python)、Javadoc(Java) 2. **静态检查**:SonarQube(检测注释覆盖率)、ESLint(强制注释规范) 3. **协作平台**:结合Git注释审查(如GitLab的Code Review功能) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值