Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
【JUGナイトセミナー】検証では成功した Java のパッチが商用でコケた件
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Takaichi00
August 26, 2020
Technology
500
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
【JUGナイトセミナー】検証では成功した Java のパッチが商用でコケた件
Takaichi00
August 26, 2020
More Decks by Takaichi00
See All by Takaichi00
individual_or_organization
takaichi00
0
370
自分から始めるアジャイルの道 ~内発的動機をきっかけに変わった価値観~
takaichi00
0
520
Java developer introduced to Rust-ADC2022
takaichi00
0
320
野球人・落合博満さんから学ぶ、アジャイルなマインドセット・プラクティス
takaichi00
1
940
【CICD2021】デプロイメントパイプラインの原理原則を再確認する / Confirm Deployment Pipeline Principle
takaichi00
11
4.8k
【JTF2021】SonarQube をより有効活用する / Effective SonarQube
takaichi00
1
2.7k
JJUG CCC 2021 Spring-Resolving OOME with JFR
takaichi00
2
3.9k
【Yahoo! JAPAN Agile 2nd】野球人・落合博満さんから学ぶスクラムマスター / デベロッパー
takaichi00
0
2.8k
【Developers Boost 2020】凡人エンジニアの生存戦略
takaichi00
1
3.4k
Other Decks in Technology
See All in Technology
渡米前の準備を制す!re:Invent 2026徹底準備術 / The Ultimate Preparation Guide for re:Invent 2026
yuj1osm
1
270
AI駆動開発における開発環境のセキュリティの考え方
yamahiro
2
620
正解のない研修に放り出されて / Being thrown into a training program with no right answers
ohnoeight
1
150
FinOps Agentが生んだ技術負債:コスト自動調査の落とし穴と解消までの道のり
oasis1994liveforever
3
300
Claude Code をローカルとサーバー上で利用した際の Bedrock 利用料をユーザー単位で一本化してみる
ohorig
0
160
AIコーディングを実践してきた1年を振り返る / Looking Back on a Year of Practicing AI Coding
takedatakashi
1
140
なぜAI時代に技術記事を書くのか?どう書くのか? 〜bunの場合〜
kworkdev
PRO
0
130
Claude Codeから見る、エンジニアの世界の変容とその先
oikon48
6
4.2k
あなたのDartコードは丸見えかもしれない ~reFlutterで暴くFlutterアプリの中身と多層防御~
zozotech
PRO
0
170
Obsidian Vault Architectures
x5gtrn
PRO
0
160
2026-10-24 JAWS JAWS-UG 茨城 #18 IAM Policy Autopilotってなにさ。terraform planからIAM Policyつくれるの? / What's IAM Policy Autopilot
masasuzu
0
170
背中から、背中へ ー 社外コミュニティで学んだ「雑に背中を押す」という恩送り ー / easygoing encouragement and pay forward to community
naitosatoshi
0
320
Featured
See All Featured
Accessibility Awareness
sabderemane
1
260
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
GitHub's CSS Performance
jonrohan
1033
470k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
59k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
270
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
Building the Perfect Custom Keyboard
takai
2
920
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
4 Signs Your Business is Dying
shpigford
187
23k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Transcript
検証では成功した Java のパッチが商用でコケた件 #JJUG 髙市 智章 (Tomoaki Takaichi) Aug, 26,
2020 【オンライン】 JJUGナイトセミナー「おうちで!ビール片手にLT大会!」
自己紹介 @Takaichi00 tomoaki.takaichi.5 ・髙市 智章(タカイチ トモアキ) ・Java / Node でのシステム開発
・CI / CD ・Container / k8s ・アジャイル開発実践 共著: クリーンなコードへの SonarQube即効活用術 http://u0u0.net/RSvx
本日お話すること ❏ 以前、検証では成功した Java のプログラムが商用で失敗 するということを経験した ❏ Java 初心者の方や教育されている方に、プログラミング 言語として
Java を知っているだけでは痛い目にあってし まうという一例になれば ※ 内容は発表に向けてカスタマイズしています
❏ 以下のような java のプログラムを作成したかった やりたかったこと id name address 1 aaa
NULL 2 bbb NULL ... … ... name register_ event aaa 1 aaa 2 bbb 1 .jar ① `address` が NULL の一覧取得 ② `name` に対応する `register_event` を取得 / 判定処理 insert.sql ④ TABLE_A に `name` に対 応する `address` を insert する SQL ファイルを作成 TABLE_A TABLE_B register_ event address 1 123 2 456 ... ... TABLE_C ③ `register_event` に対応する `address` を取得 / 判定処理
❏ 実装したプログラムの概要は以下の通り 問題の実装コードと実行コマンド public static void main(String[] args) throws SQLException
{ List<UpdateAttribute> updateAttributes = null; try (Connection con = DriverManager.getConnection(connectionUrl, "user", "pass")) { updateAttributes = new ArrayList<>(); String sql1 = "SELECT id,name,address FROM TABLE_A WHERE address is NULL"; PreparedStatement stmt1 = con.prepareStatement(sql1); ResultSet rs1 = stmt1.executeQuery(sql1); // SELECT したすべてのデータを List に格納 while (rs1.next()) { updateAttributes.add(new UpdateAttribute(rs1.getInt("id"), rs1.getString("name"), null)); } for (UpdateAttribute updateAttribute : updateAttributes) { // List をループして更に別テーブルに SELECT 文を実行 while (rs2.next()) { // なんらかの業務ロジック … 省略 } public static void main(String[] args) throws SQLException { … 省略 for (UpdateAttribute updateAttribute : updateAttributes) { // List をループして更に別テーブルに SELECT 文を実行 while (rs2.next()) { // なんらかの業務ロジック ... String sql3 = "SELECT name,address FROM TABLE_B WHERE name='" + <ロジックから取得できた値> + "'"; while (rs3.next()) { // なんらかの業務ロジック ... updateAttribute.setAddress(rs3.getString("address")); } } } // SQL ファイル出力処理 ... } catch () … // 例外処理 }
❏ 複数回実行されていた PreparedStatement や ResultSet は それぞれ close されていなかった ❏
SELECT 文で取得できた ResultSet の結果を List に一括代入 ❏ 実行する際は起動オプションを指定せず、単純に「java -jar ~~.jar」と実行 問題の実装コードと実行コマンド
❏ ローカル PC (メモリ 16GB) から、検証用のデータが入っ た検証用 DB へ向けてこのパッチを起動したところ、問題 なく実行が完了した
(データ量は数十件程度) 検証の構成では成功 検証環境 成功 メモリ: 16GB
❏ 商用環境では VM 上 (メモリ 1GB) で作成したパッチを実 行した。しかし処理が全然完了しなかった ❏ 商用のデータ量は検証環境よりは多いが、たかだか1万件
未満程度のもの 商用環境では失敗 商用環境 失敗 メモリ: 1GB
❏ java -jar コマンド実行時の引数に -Xlog:gc* を追加して GC ログの詳細を表示してみる ❏ すると
FullGC が多発していることがわかった GC ログを出してみる $ java -Xlog:gc* -jar hoge.jar ... [81.318s][info][gc ] GC(29) Pause Full (G1 Evacuation Pause) ... [81.318s][info][gc,cpu ] GC(29) User=0.05s Sys=0.00s Real=0.02s
❏ JVM にはエルゴノミクスというプロセスがあり、マシンの スペックに応じてヒープサイズが自動決定される ❏ デフォルトでは以下の設定となっている ヒープオプションを追加する 初期ヒープ・サイズ 物理メモリーの 1/64
(最大1GB) 最大ヒープ・サイズ 物理メモリの 1/4 (最大1GB) ❏ jar 実行時に、-Xms512M -Xmx512M のようにヒープサ イズを設定することで、時間はかかったが処理を完了させ ることができた
⇒ 検証するため、再度似たようなプログラムを作成して GC Viewer を用いて解析をしてみる ❏ 仮説1: PreparedStatement / ResultSet
の close 忘れ ❏ 仮説2: 最初に SELECT で一気にテーブルの値を List に格 納してしまったことでヒープサイズを圧迫 そもそも実装コードが悪い
❏ 似たようなプログラムをヒープサイズを指定し、GC ログを 出力するようにして実行した結果、処理が進むに連れ FullGC が発生して最終的に OOME が発生した (データ量約1万件) 問題のプログラムを解析する
$ java -Xlog:gc:./gc.log \ -Xlog:gc* \ -Xms20M -Xmx20M -jar hoge.jar
❏ PreparedStatement / ResultSet を close するよう処理 を修正したところ FullGC は発生せず適切にメモリが開放
されて処理が継続できた (データ量約1万件) 仮説1: PreparedStatement / ResultSet の close 忘れ
❏ close 処理を実施し、データ件数を1万件から2万件に変更し て実行したが、初期のヒープサイズがやや増加したのみ。 よって今回ではクリティカルな問題ではなかった。 仮説2: List に全件のデータを格納してしまった
まとめ ❏ ヒープサイズは指定するようにする (エルゴノミクス) ❏ close 処理を怠らない ❏ DB からデータを取得して
Java メモリ上に大量のデータ を格納するような処理はしない ❏ GC ログや GC Viewer の利用方法を知っておくと便利 ❏ できるなら商用環境のデータ量でテストを実施する
まとめ ❏ 今回ではプログラミング言語として Java を知っているだ けでは痛い目にあうという一例を紹介した ❏ Java をこれから始めようとされている方 /
Java を教えて いる方などの参考になれば幸いです
❏ エルゴノミクス (Oracle 公式) ❏ Java開発の性能改善! その2 GCログの解析とHeapの設定 ❏ JavaのGCの仕組みを整理する
❏ JavaのGCに関するオプションについてまとめてみた。 ❏ JVM入門 -Javaプログラムが動く仕組み- ❏ Statement の解放漏れには気をつけよう ❏ MySQL Connector/J (JDBC ドライバ)の罠まとめ ❏ MySQL+Connector/Jを使って、大量データのSELECT⇒INSERTした時の挙動を確認する ❏ JDBC setFetchSize() ではまった話 ❏ JDBC経由で100万件取得・追加してみた ❏ Java いまふたたびのJDBC 参考文献
ご清聴ありがとうございました