1. SecureRandomとは
SecureRandomは、**暗号論的に安全な乱数(CSPRNG:Cryptographically Secure Pseudo-Random Number Generator)**を生成するためのJavaクラスです。
java.securityパッケージに含まれ、セキュリティトークン、APIキー、暗号鍵などの生成に利用されます。
通常のRandomクラスは予測可能な乱数を生成するため、攻撃者にシードを特定される危険性があります。
対してSecureRandomはOSの暗号エンジンを利用して予測不能な乱数を生成します。
2. Randomとの違い
| 項目 | Random | SecureRandom |
| 主な用途 | ゲーム・抽選・シミュレーション | 暗号・セキュリティ関連 |
| 再現性 | シード指定で再現可能 | 予測困難・安全性重視 |
| エントロピー源 | 疑似乱数(数列) | OSの乱数エンジン |
| パフォーマンス | 高速 | やや低速(安全性優先) |
| 実装場所 | java.util | java.security |
3. Javaバージョン別の対応ポイント
| バージョン | 特徴・変更点 |
| Java 8 | 最も広く使われる環境。SecureRandomはデフォルトで十分安全。getInstanceStrong()も使用可能(JDK実装依存)。 |
| Java 11 | Base64.getUrlEncoder()などの標準エンコーダが安定。マルチスレッド環境でのSecureRandom利用も改善。 |
| Java 17 (LTS) | デフォルトの乱数アルゴリズムが強化(DRBGが推奨)。新しいSecureRandom実装が追加。 |
| Java 21 (LTS) | SecureRandomのアルゴリズム選択がより細かく制御可能に。DRBGがデフォルトで推奨パス。 |
💡 DRBGとは?
Java 17以降では、NIST標準(SP800-90A)に準拠したDRBG(Deterministic Random Bit Generator)が使用可能です。
これは暗号学的により強固な乱数生成手法で、今後の推奨実装となります。
4. サンプルコード:安全なトークン生成
🧩 出力例:
5. 高度な使い方(Java 17以降対応)
✅ 強力なDRBGインスタンスを明示的に取得
💡 HexFormatはJava 17で追加された便利クラスです。
Base64よりも短い表現でログ出力に適しています。
6. よくある利用シーン
| シーン | 使用目的 | 推奨API |
| 認証トークン生成 | セッションIDやAPIキー | SecureRandom + Base64 |
| CSRFトークン | Webフォームの保護 | SecureRandom + HexFormat |
| パスワードリセットURL | 予測困難な一時リンク生成 | getInstanceStrong() |
| 暗号鍵生成 | AESなどの鍵素材 | SecureRandom |
| UUID代替 | 高強度ランダムID | SecureRandomで独自生成 |
7. ベストプラクティス
| 推奨事項 | 理由 |
| SecureRandomの使い回し | 毎回生成するとコストが高い |
| OS依存のソースを活用 | /dev/urandomなどで高品質な乱数 |
| getInstanceStrong()を必要時のみ使用 | 起動が遅くなるため常用は非推奨 |
| Base64やHexFormatで可読化 | ログやトークンで扱いやすい |
| シード指定は避ける | セキュリティが低下するため |
8. パフォーマンス比較(目安)
| 操作 | 平均速度 | 安全性 |
| Random.nextInt() | 非常に高速 | 低 |
| SecureRandom.nextInt() | 中程度 | 高 |
| SecureRandom.getInstanceStrong() | やや遅い | 最高 |
| SecureRandom (DRBG) | 中〜高 | 最高(推奨) |
9. まとめ
| ポイント | 内容 |
| 用途 | 暗号・認証・トークン生成に最適 |
| バージョン対応 | Java 8〜21全対応 |
| 推奨実装 | SecureRandom または DRBG(Java 17+) |
| 注意点 | シード指定・再生成の多用を避ける |
| 一言 | 安全性を重視する場面では必ずSecureRandomを! |
🧠 コラム:SecureRandomを使うべき「具体例」
-
OAuth 2.0 認可コードの生成
-
JWTの署名鍵生成
-
Cookieのsession_id生成
-
APIトークン・CSRFトークン・暗号鍵など
→ 「ユーザーや外部に漏れたら困る値」には必ずSecureRandom!
JavaでSQL接続を扱うとき、多くの初心者が陥るのが「リソースの解放忘れ」や「例外処理の煩雑さ」です。
特に Connection, PreparedStatement, ResultSet の3つは明示的に close() しないと、メモリリークや接続枯渇の原因になります。
この記事では、そんな問題をtry-with-resources構文でスマートに解決する方法を紹介します。
🧱 try-with-resourcesとは?
Java 7以降で導入された構文で、AutoCloseable インターフェースを実装したオブジェクトを
自動的にクローズしてくれる仕組みです。
✅ 従来のコード例(Java 6以前)
🚀 try-with-resourcesを使った改良版
🧠 複数リソースを扱うときのポイント
try(...) の中で複数のリソースを「セミコロン ;」で区切って宣言できます。
最後に開いたリソース (ResultSet) から順に自動クローズされます(LIFO順)。
⚙️ try-with-resourcesとカスタムクラス
自作クラスでも AutoCloseable を実装すれば、
try-with-resources構文で安全に自動クローズが可能です。
⚠️ 注意点:例外の隠蔽に注意
もし try 内と close() 内の両方で例外が発生した場合、
try 内の例外が優先され、close() の例外は「抑制された例外」として記録されます。
🔍 まとめ
| ポイント | 内容 |
| 構文 | try(リソース宣言){ ... } |
| バージョン | Java 7以降 |
| 対応型 | AutoCloseableを実装する全クラス |
| 主な利点 | コード簡略化・例外安全性・リソースリーク防止 |
💬 おわりに
try-with-resources は見た目以上に強力です。
「リソース管理を明示的に書かない」だけで、コードの信頼性と保守性が大幅に向上します。
特にSQL接続まわりでは、この構文を使わない理由がないほどの必須テクニックです。
今後のJava開発では「標準の書き方」として身につけておきましょう。
1. assertThrowsとは?
JUnit5で例外をテストする際に便利なのが assertThrows です。
従来は try-catch を使って例外を検証していましたが、コードが冗長になりがちでした。JUnit5から追加された assertThrows を使うと、例外発生をシンプルにテストできます。
2. 旧来のtry-catch方式との比較
JUnit4までの書き方は以下のようになります。
fail を入れたり、catchブロック内で assertEquals を書く必要があり、テストコードが長くなっていました。
assertThrows を使えば、これを 1行でシンプルに記述可能 です。
3. 例外メッセージの検証
assertThrows は戻り値として発生した例外オブジェクトを返すため、メッセージや詳細を検証することも可能です。@Test
4. 複数の例外クラスに対応
もし異なる種類の例外が発生する可能性がある場合、複数の assertThrows を組み合わせてテストできます。
5. assertThrowsを使うメリットまとめ
まとめ
JUnit5の assertThrows を使えば、例外発生テストがとてもスッキリ書けるようになります。
「テストコードの読みやすさ・保守性を高めたい」という方には必須のテクニックです。
これを取り入れるだけで、テストがより楽しく、効率的になるので試してみましょう!
Java開発におけるログ出力は、障害解析・性能改善・監査の三種の神器。長年使われてきた log4j 1.x に対し、後継の log4j2 は「高速・柔軟・安全」に大幅進化しています。本稿では、違いが直感的に分かる比較と、**失敗しない導入手順(Maven/Gradle、設定、非同期化、移行の落とし穴まで)**をまとめます。
1. log4j 1.x と log4j2 の要点比較
| 観点 | log4j 1.x | log4j2 |
| パフォーマンス | 同期中心。大量ログでアプリに負荷 | LMAX Disruptorによる非同期ロガーで高速・低レイテンシ |
| 設定形式 | properties / XML のみ | XML / JSON / YAML / properties、ホットリロード対応 |
| 非同期化 | AsyncAppenderのみ | AsyncAppender+Async Logger(全ロガー非同期も可) |
| GC負荷 | 文字列連結が発生しやすくGC負担増 | 遅延評価(ラムダ/プレースホルダ)で不要時は連結処理なし |
| 拡張性 | 限定的 | フィルタ / レイアウト / Appender が豊富(JSON出力、Failover等) |
| メンテナンス | EoL(保守終了) | 現行バージョン維持(常に最新2.xを推奨) |
結論:高負荷・可観測性重視の現場ほど log4j2 一択。
2. こんな場面で「log4j2」を選ぶ
-
大量ログ(秒間1000件~万件)を裁くWeb/バッチ、IoT、決済、EC
-
本番でログレベルを動的変更したい(再起動なしで即調査)
-
JSON出力で Elasticsearch / OpenSearch / Splunk / Datadog に流す
-
遅延評価や MDC(相関ID) で可観測性とパフォーマンスを両立したい
3. 導入手順(Maven/Gradle)――最短で“動く”まで
ここでは log4j2 を実装(Core)として使い、APIは SLF4J で書く構成を推奨します。
理由:ライブラリ間の共通言語として SLF4J がデファクト、実装差し替えも容易。
3.1 依存関係を追加
Maven(pom.xml)
Gradle(Kotlin DSL)
重要:既存で引き込まれる logback-classic や slf4j-log4j12 は除外してください(重複実装エラー&二重出力の原因)。
3.2 旧実装の衝突を避ける(例:Maven の除外)
3.3 最小構成の設定ファイル(src/main/resources/log4j2.xml)
3.4 SLF4J での利用コード
3.5 ローリングファイル+JSON(実戦向け)
3.6 非同期化の推奨設定(高スループット向け)
方法A:Async Appender(部分的に非同期)
方法B:Async Logger(全ロガーを非同期化)
-
依存に disruptor を追加(前述)
-
JVM 起動オプションに以下を付与
|
|
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector |
目安:秒間数千件以上のログ、遅延許容な処理では Async Logger が強力。
低遅延の必要なクリティカル処理(トランザクション境界直前など)は同期Appenderで分離も可。
3.7 現場で必須の“相関ID”(MDC/ThreadContext)
3.8 動的なログレベル変更(コード&設定)
3.9 他フレームワークのログを一本化(任意)
4. 旧 log4j 1.x からの移行チェックリスト
-
jar の置換と衝突解消
-
1.x の log4j-1.2.x.jar を除去
-
log4j-api, log4j-core, log4j-slf4j2-impl を追加
-
他実装(logback 等)を除外
-
設定ファイルを置き換え
-
コードの修正方針(推奨順)
-
SLF4J API へ書き換え(LoggerFactory.getLogger 等)
-
もしくは log4j2 API へ(org.apache.logging.log4j.LogManager.getLogger)
-
当面の暫定策として log4j-1.2-api(互換レイヤ)もあるが恒久利用は非推奨
-
性能と出力の検証
-
運用監視
5. 開発・運用の実用Tips
-
重い toString() を直接連結しない:log.debug("x={}", () -> obj.heavyToString())
-
Failover Appender で出力先障害に備える(ネットワークストレージ等)
-
パターン設計:時刻、レベル、ロガー、メッセージ、%throwable、MDC を最低限
-
本番では INFO 以上、詳細調査時のみ一時的に DEBUG/TRACE を開ける
-
最新 2.x 系を採用(セキュリティ修正が継続されるため)
6. まとめ
-
log4j2 は “高速+柔軟+安全”。大量ログ・可観測性要件に強い。
-
導入は依存追加 → 設定作成 → 非同期化の3ステップが核。
-
移行は衝突除去と設定変換が肝。SLF4J API で書くと将来の実装差し替えも容易。
HULFTには「送受信ジョブを定義して使う方法」以外に、utlsendなどのユーティリティ系コマンドを直接呼び出してファイル転送や加工を行う手段があります。
これらは事前の送受信定義が不要で、コマンド実行時に条件を指定できるため、テスト送信・スポット利用・簡易処理に非常に便利です。
本記事では、JavaでHULFTコマンドを実行する例をご紹介します。
-
utlsend : ファイル送信
-
utlrecv : ファイル受信
-
utlconcat : ファイル連結
-
utlsplit : ファイル分割
Javaから外部コマンドを実行する基本
Javaでは ProcessBuilder を使うことで、外部のHULFTコマンドを呼び出せます。
エラー出力も標準出力にまとめる設定をすれば、ログ管理が容易になります。
共通の呼び出しテンプレートは以下の通りです。
1. ファイル送信(utlsend)
事前の送信定義が不要で、対象ファイルと宛先ノードを直接指定できます。
-
-f : 送信するファイルパス
-
-n : 宛先ノード名(HULFTに登録済み)
2. ファイル受信(utlrecv)
受信ジョブを登録せず、コマンドだけでファイルを取得できます。
-
-f : 保存先のファイル名
-
-n : 送信元ノード名
3. ファイル連結(utlconcat)
複数のファイルを1つにまとめたいときに使います。
|
|
public class ExampleConcat { public static void main(String[] args) { HulftCommandRunner.runCommand( "utlconcat", "-o", "/data/merged.txt", "-f", "/data/file1.txt", "-f", "/data/file2.txt" ); } } |
-
-o : 出力ファイル名
-
-f : 結合対象のファイル(複数指定可)
4. ファイル分割(utlsplit)
大きなファイルを分割して処理したいときに使います。
-
-f : 分割対象ファイル
-
-l : 分割する行数(例:1000行ごと)
運用上の注意点
-
PATHの設定
Javaから呼び出す際は、utlsend.exe などのHULFTバイナリがPATHに通っている必要があります。
通っていない場合はフルパス指定が必須です。
-
終了コードの確認
-
ログ管理
実際の業務バッチでは process.getInputStream() の内容をファイル出力してログ管理することを推奨します。
まとめ
-
utlsend でファイルを即送信できる
-
utlrecv で即時受信が可能
-
utlconcat でファイルを連結
-
utlsplit でファイルを分解
これらをJavaから呼び出すことで、柔軟なファイル連携や加工処理が実現できます。
GCとは何か
Java で開発をしていると、よく耳にする「GC(Garbage Collection)」。
これは 不要になったオブジェクトを自動で回収してメモリを解放する仕組み のことです。C言語のように手動で free() を呼ぶ必要はなく、Java VM が裏側でメモリ管理を行います。
ざっくり構造・最近のGC
-
世代別回収:Eden/Survivor(若世代)→ Old(老世代)
-
Minor GC:Edenが埋まったら短命オブジェクト中心に回収
-
Major/Full GC:Oldが逼迫、断片化、クラス/メタ領域逼迫などで広域回収
-
既定GC:G1GC(Java 9+)。低停止要求は ZGC / Shenandoah も選択肢
主なトリガ
“悪い例 → 良い例”で学ぶメモリ/GC対策
1) 無制限キャッシュ(静的Map地獄)
悪い例
ポイント:上限なしは必ずOldを膨らませる。キャッシュは 容量・期限・エビクションを設計。
2) リスナ/コールバック未解除
悪い例
3) ThreadLocal の放置(プールスレッドに張り付く)
悪い例
良い例(finallyで確実に除去)
4) System.gc() 乱用
悪い例
5) ラムダ/内部クラスが外側(巨大オブジェクト)をキャプチャ
悪い例
良い例(必要最小限のデータだけ渡す・static化)
ポイント:キャプチャ=保持。意図せず大物を延命していないか疑う。
6) ループ内の大量一時オブジェクト
悪い例
良い例(StringBuilder再利用・ボクシング回避)
7) finalize/Cleaner頼み(遅延・不確実)
悪い例
8) クラスローダ・アプリ再デプロイ時のリーク
悪い例
良い例(クラスローダ境界を越える参照を断つ)
9) 巨大配列・Humongous割当ての長期保持(G1)
悪い例
良い例(分割・ストリーミング・寿命短縮)
ポイント:巨大ブロックは断片化と回収コスト増の温床。
10) 無制限のキュー/バッファ
悪い例
良い例(有界+バックプレッシャ)
GCログ・計測の始め方(JDK 9+)
-
まずはコードの割当て削減 → その後にヒープ/GC調整
-
監視:jcmd <pid> GC.heap_info / jstat -gc <pid> 1000
-
ボトルネック特定:JFR(Java Flight Recorder) で割当てホットスポットを把握
-
必要なら ZGC/Shenandoah も評価(レイテンシ目標に応じて)
実務チェックリスト(配布推奨)
-
System.gc() を禁止/抑制
-
キャッシュ・キューは有界+期限
-
ThreadLocal は finally で remove
-
リスナ/コールバックは確実に解除(AutoCloseable化が効く)
-
ループ内の一時オブジェクトを減らす(Builder再利用/ボクシング回避)
-
巨大配列は分割・短命化
-
クラスローダ境界を跨ぐ静的参照禁止、Executor停止・ドライバ解除
-
try-with-resourcesでオフヒープ即時解放
-
GCログ/JFRで事実ベースに調整
-
目標停止時間(例:MaxGCPauseMillis)を定めて検証
まとめ
GCは“自動”でも“万能”ではありません。
「GCが働きやすいコード」(不要参照を残さない・波及して大物を掴ませない・ピークメモリを避ける)を心がけ、ログ/計測で改善ループを回すのが最短距離です。
「駑馬十駕」を信念に IT系情報を中心に調べた事をコツコツ綴っています。