JVMさん、誇張しているわけではありません。

JVMさん、誇張しているわけではありません。

[[410405]]

JVM が Java にとって、そしてプログラマーの面接にとってどれほど重要であるかは言うまでもありません。

JVM を学習する必要性を認識していない場合、または JVM を学習する方法がわからない場合は、この記事を読めば答えがわかります。

以前は JVM を学ぶことを嫌っていましたが、後になって学ぶ必要があることに気づきました。妻と口論した後に謝りたくないのと同じです。謝らないのは不可能だ。謝罪は遅かれ早かれ起こることであり、それを避けることはできません。

その時私は理解しました:

敗北を認めるのが遅くなればなるほど、結果は悪くなります。

しかし、学習しているうちに、JVM は多すぎて、学習するのが難しすぎることに気づきました。

私の学習過程は非常に困難だったと言えますが、浮き沈みを経て、JVM を学習する方法はたくさんあることがわかりました。

私の経験と同僚との議論に基づいて、JVM を学習する最良の方法は次のとおりです。

さまざまなレベルのプログラマーに正確な学習を提供します。

いわゆる精密学習とは、仕事に大いに役立つ知識ポイントを学習することを意味します。作業コンテンツを使用して学習を促進します。十分な知識を蓄積したら、JVM のすべての知識ポイントを一挙に習得し、最終的には JVM の基本原理を習得できます。

次に、ジュニア、シニア、経験豊富なプログラマーが段階的に学習する方法について説明します。

ジュニアプログラマーとして学ぶ方法

業界に入ったばかりの初心者プログラマーの仕事は、一般的には簡単なバグを修正したり、簡単な機能を開発したりすることです。バグを少なくしてコーディングする方法が、この段階での中心的な問題です。

この核心的な問題については、JVM の原則に関する 2 つの知識ポイントを深く習得する必要があります。

1. クラスの初期化

クラスの初期化には非常に深い理解が必要です。そうしないと、気付かないうちに初期化バグがプロジェクトに導入される可能性があります。

たとえば、次のコードを考えてみます。

  1. パブリッククラス ParentClass {
  2. プライベートint親X;
  3. パブリック親クラス() {
  4. Xを100に設定します。
  5. }
  6. パブリックvoid setX( int x) {
  7. 親X = x;
  8. }
  9. }
  10.  
  11. パブリッククラスChildClassはParentClassを拡張します{
  12. プライベートint childX = 1;
  13. パブリックChildClass() {}
  14. @オーバーライド
  15. パブリックvoid setX( int x) {
  16. スーパーセットX(x);
  17. 子X = x;
  18. システム。 out .println( "ChildX は " + x に割り当てられます);
  19. }
  20. パブリックボイドprintX() {
  21. システム。 .println( "ChildX = " + childX);を出力します
  22. }
  23.  
  24. }
  25.  
  26. パブリッククラスTryInitMain {
  27. 公共 静的void main(String[] args) {
  28. ChildClass cc = 新しい ChildClass();
  29. cc.printX();
  30. }
  31. }

興味があれば実行して結果を確認することができます。この種のコードが本番環境に導入されると、トラブルシューティングが非常に困難になります。

2. Javaのメモリ構造とオブジェクトの割り当て

2 番目の知識ポイントは、Java のメモリ構造とオブジェクトの割り当て、特に JVM メモリ内のヒープ レイアウトとオブジェクトの割り当ての関係に関する基本的な知識です。

例えば、ヒープメモリのレイアウト

もちろん、Java7以降では新しいレイアウトが変更されました

レイアウトを知るには、Java オブジェクト割り当ての基本原則を知る必要があります。

  • オブジェクトはまずEden領域に割り当てられます
  • 大きすぎるオブジェクトは古い世代に直接割り当てられます

この知識を知っているだけで、次のようなバグを頻繁に書き留めることはなくなります。

  1. // すべての行をメモリに読み込む
  2. List<String> 行 = FileUtils.readLines(新しい File( "temp/test.txt" ), Charset.defaultCharset());
  3. for (文字列行:行数) {
  4. // 合格
  5. }

上記のコードは、大きなファイルを読み取ると本番環境をクラッシュさせる可能性があります。

したがって、上記の 2 つの知識ポイントを深く理解することは、初心者がコードの品質を向上させるのに非常に役立ちます。コードの品質が向上して初めて、より良い開発を実現できます。

これら2つの知識については、インターネット上の記事を通じて学ぶのが最善だと思います。本を直接読む場合、最大の欠点が 2 つあります。

  • 知識の蓄積が不十分だと学習能力が失われる
  • この本には冗長な知識ポイントが多すぎて、互いに絡み合ってエネルギーを消費しすぎて、費用対効果が高くない

したがって、ここでの推奨は、原則に関する本を探すのではなく、知識ポイントに基づいて記事を検索することです。

上級プログラマーの学習方法

この段階の友人は、すでに堅牢なコードを巧みに記述でき、大規模な機能モジュールを独自に開発できる場合が多く、中には完全な小規模プロジェクトを独自に開発できる人もいます。

現時点では、次の 2 つの状況に直面する可能性があります。

1. チーム全体で使えるツールを作成する必要がある

この場合、おそらく Java の構文糖が必要になります。構文糖を使用すると、非常に柔軟でシンプルなコードを記述できるためです。これには、ジェネリック、自動アンボックス化、可変引数、ループが含まれます。

ただし、これらの構文シュガーを使用する場合、JVM での実装原則に精通していないと、大きな間違いを犯してしまう可能性が非常に高くなります。

例えば:

  1. パブリッククラス GenericPitfall {
  2. 公共 静的void main(String[] args) {
  3. リスト list = new ArrayList();
  4. リスト「123」を追加します
  5. リスト<整数> list2 = リスト;
  6. システム。出力.println(list2.get(0).intValue());
  7. }
  8. }

2. 高性能なコードを書く

優れたパフォーマンスを備えたコードが必要になるのはいつでしょうか?最も一般的なのは、パフォーマンスの悪い以前の同期実装を非同期実装に変換することです。

この要件を満たすには、開発者は Java マルチスレッド開発に精通し、JVM におけるマルチスレッドの原理と実装を深く理解している必要があります。

それ以外の場合は、次のコードを確認してください。

  1. クラス IncompleteSynchronization {
  2. 整数x;
  3.  
  4. 公共 整数getX() {
  5. xを返します
  6. }
  7.  
  8. パブリック同期void setX( int x) {
  9. this.x = x;
  10. }
  11. }

この段落をもう一度見てください。

  1. オブジェクトロック = 新しいオブジェクト();
  2. 同期(ロック){
  3. ロック = 新しいオブジェクト();
  4. }

上記のコードを本番環境に導入すると、問題のトラブルシューティングのために夜通し作業することになります...

ここでの知識ポイントについては、オンライン記事を読むことをお勧めします。並行性の知識も関係するので、「Java パフォーマンス」第 2 版の「第 9 章 スレッドと同期のパフォーマンス」も併せて読むことをお勧めします。

まだ体力に余裕があるなら、周志明の著書『JAVA 仮想マシンの徹底理解』第 3 版の第 12 章から第 13 章を読み続けることをお勧めします。周志明氏の本は非常に詳細ですが、敷居が高いという欠点もあります。この時点で、理解できない場合は脇に置いておいてもかまいません。

ここで私が話しているのは並行性の実践ではなく、並行性の原則であることに注意してください。読者が並行プログラミングを学習したい場合、「JAVA 並行プログラミング実践」が前提条件になると思うので、これについては詳しく説明しません。

上級プログラマーはどのように学ぶのか

この時点で、あなたはすでにプロジェクト開発において非常に重要な責任を引き受け始めており、優秀な友人たちがチームを率い始めています。この時点で、次の操作を実行できます。

1. プロジェクトリソースを合理的に計画する

プロジェクトのリソース使用を合理的に計画するには、廃棄物のリサイクルに関する非常に深い理解が必要です。

初心者の段階で Java オブジェクトのメモリ割り当てとメモリ使用量について既に一般的な理解がある場合、ガベージ コレクションはこの知識をさらに拡張したものになります。

さまざまなガベージ コレクションの原理を理解し、Java メモリ レイアウトの基礎知識を組み合わせることによってのみ、プロジェクトで使用するリサイクル アルゴリズムをより適切に計画し、適切なリソース使用率で最高のパフォーマンスを得ることができます。

たとえば、新世代と旧世代の適切な比率などです。たとえば、新世代におけるエデンエリアとサバイバーエリアの比率。

2. さまざまなオンラインの問題のトラブルシューティング

さまざまな問題をトラブルシューティングするには、JVM が提供するさまざまなトラブルシューティング ツールを十分に理解する必要があります。

これらのツールは次の 2 つのカテゴリに分類されます。

  • jps、jstack などの基本的なコマンドライン トラブルシューティング ツール。
  • 2番目のカテゴリは、VisualVMなどの視覚的なトラブルシューティングツールです。

しかし、ツールの使い方を習得するだけでは十分ではありません。ガベージ コレクションの問題については、GC ログを分析し、ツールを使用して問題の根本原因を特定する必要があります。

したがって、トラブルシューティング ツールと GC ログの両方を使いこなせるようになることが最善です。

例えば:

  1. 2021-05-26T14:45:37.987-0200: 151.126:
  2. [GC (割り当て失敗) 151.126: [DefNew: 629119K->69888K(629120K)、0.0584157 秒] 1619346K->1273247K(2027264K)、0.0585007 秒]
  3. [時間:ユーザー=0.06、システム =0.00、実数=0.06 秒]
  4.  
  5. 2021-05-26T14:45:59.690-0200: 172.829:
  6. [GC (割り当て失敗) 172.829: [DefNew: 629120K->629120K(629120K), 0.0000372 秒]172.829: [Tenured: 1203359K->755802K(1398144K), 0.1855567 秒] 1832479K->755802K(2027264K), [メタスペース: 6741K->6741K(1056768K)​​], 0.1856954 秒]
  7. [時間:ユーザー=0.18、システム =0.00、実数=0.18 秒]

上記から、ガベージ アルゴリズムが Serial コレクターを使用しており、若い世代の割り当てに問題があり、サイズを調整する必要がある可能性があることが一目でわかるはずです。

ここでの知識ポイントについては、オンライン記事を読まないことを強くお勧めします。オンラインで言及されている詳細の多くは問題があり、省略されている部分も多数あります。ですので、この本を読むことをお勧めします。

『Java パフォーマンス』第 2 版の「第 5 章 ガベージ コレクションの概要」と「第 6 章 ガベージ コレクション アルゴリズム」の知識があれば十分です。

ガベージ コレクターとメモリ割り当て戦略について説明している「JAVA 仮想マシンの詳細な理解」の第 3 版の第 3 章を読む人もいます。これはまだ古い問題であり、議論が詳細すぎます。 HotSpot アルゴリズムの詳細について説明しているセクション 3.4 はスキップすることをお勧めします。

ここでの安全性の知識ポイントは非常に重要ですが、現段階では理解するのが困難です。将来、基盤となるフレームワークに取り組んでクラッシュ回復のチェックポイント関連のアイデアに触れる機会があったら、戻って勉強すれば、本当に理解して習得できると思います。

技術専門家はどのように学ぶのか

このレベルに達すると、技術的な問題を解決できる最後の保証人となるため、JVM 全体について非常に深い理解が必要になります。場合によっては、特定の問題のためにさまざまなツールを開発する必要があることもあります。

昔々、常に時々エラーを報告するプロジェクトがありました。

  1. java.lang.OutOfMemoryError: GC オーバーヘッド制限を超えました

何人かの同僚がこの問題を解決できなかったので、私に相談に来ました。見てみると、公式のチューニングガイド「HotSpot Virtual Machine Garbage Collection Tuning Guide」で関連する紹介を見たことがあるのを突然思い出しました。

JVM 自体のメモリが不足すると、GC が実行されます。ただし、各 GC によって回収されたメモリが十分でない場合は、次の GC がすぐに開始されます。

JVM にはデフォルトの保護メカニズムがあります。統計期間中に GC が 98% の時間実行されているが、メモリ回復が 2% 未満であることが判明した場合、このエラーが報告されます。

それはどのように起こるのでしょうか?コードのトラブルシューティングを行おうとすると、非常に困難になります。まず、問題の特定に役立つスタック エラーがありません。第二に、プロジェクト コードは巨大で、非常に古いです。

この時点で、JVM 全体を深く理解して問題を解決する必要があります。私はこう考えました:

メモリ オーバーフローと GC のリサイクル失敗は、次の 2 つの問題を示しています。

  • ヒープ内のメモリが不足しています
  • メモリを占有しているオブジェクトは、閉じられるべきであるが閉じられていないリソース、または一時的に大量にまとめられているリソースのいずれかです。

メモリ ファイルをダンプして分析すると、どのオブジェクトがメモリを占有しているかがわかります。

確認してみると、大量の文字列がメモリを占有していることが判明しました。

以前の推測に基づくと、文字列はデータベース接続ではないため、閉じなくても問題は発生しません。そうすると、残る可能性は 1 つだけ、つまり、大量のデータが一時的に保管され、GC がそれをリサイクルできなくなるということになります。

そこで新たな疑問が生じます。大量の文字列を保存できるものは何でしょうか?

まず、キャッシュを推測します。この手がかりに従って、ソースコード内で直接 Cache キーワードを検索し、Cache に関連するすべてのコードを読み取りました。問題はすぐに見つかりました。

非常に大きなファイルを解析する関数があることがわかりました。ファイルの形式は次のとおりです。

このファイルの各行を列に従ってデータベースに保存する必要があります。

コード作成者が怠け者だったため、一度にすべてのデータを解析してからデータベースに詰め込もうとしました。そこで、キーが同じ列名で、値が各行の解析されたコンテンツであるマップを作成しました。

このようにコードを記述すると、1 つの行が 3 つのエントリを持つ HashMap に対応することになります。ファイルに数十万行ある場合、HashMap も数十万個存在します。次に、これらの HashMap はリストに保存され、このリストは xxxCache と呼ばれる HashMap に格納されます。

回路図コードは次のとおりです。

  1. パブリッククラス ParseFile4OOM {
  2. 公共 静的void main(String[] args) {
  3. リスト<Map<String, String>> lst = new ArrayList<>();
  4. ( int i = 0; i < 100000; i++) {
  5. Map<String, String> map = new HashMap<>();
  6. map.put( "列1" "コンテンツ1" );
  7. map.put( "列2" , "コンテンツ2" );
  8. map.put( "列3" "コンテンツ3" );
  9. lst.add (マップ);
  10. }
  11.  
  12. Map<String, List<Map<String, String>>> contentCache = new HashMap<>();
  13. contentCache.put( "コンテンツ" 、lst);
  14. }
  15. }

では、このような状況では私たちは何をすべきでしょうか?コードを大幅に変更することはできず、最適化することしかできません。

当時、私たちはすでに String 定数プールを導入した JDK8 を使用していました。同時に、このビジネス シナリオでは、Hashmap の容量は固定されているため、これ以上のスペースを割り当てることはできず、3 に固定されます。

最適化後のコードは次のようになります。

  1. パブリッククラス ParseFile4OOM {
  2. 公共 静的void main(String[] args) {
  3. リスト<Map<String, String>> lst = new ArrayList<>();
  4. ( int i = 0; i < 100000; i++) {
  5. Map<String, String> map = new HashMap<>(3);
  6. map.put( "列1" .intern(), "コンテンツ1" .intern());
  7. map.put( "列2" .intern(), "コンテンツ2" .intern());
  8. map.put( "列3" .intern(), "コンテンツ3" .intern());
  9. lst.add (マップ);
  10. }
  11.  
  12. Map<String, List<Map<String, String>>> contentCache = new HashMap<>();
  13. contentCache.put( "contents" .intern(), lst);
  14. }
  15. }

最適化されたコードをオンラインにすると、エラーが修正されます。

したがって、この段階では、JVM を完全に理解する必要があります。原則を完全に理解するには、本を読まなければなりません。

周志明の「JAVA 仮想マシンの詳細な理解」は必要ですが、それだけでは十分ではありません。

また、「Oracle JRockit: The Definitive Guide」という本を読むこともお勧めします。古い本ですが、特に最初の 4 章の内容の多くで、JVM の原理が徹底的に説明されています。 JVM がリソースとパフォーマンスのバランスをとるためにどのように弾力的にスケーリングするかについての詳細な説明は非常に啓発的で、私のプログラミングの視野を広げてくれました。

ここまで、段階ごとの学習方法について説明しました。

一般的に、JVM の知識は広範囲かつ複雑であり、習得したければ一夜にして習得できるものではありません。さらに、私たちプログラマーにとってそれは簡単なことではありません。私たちは多くの知識を学ぶ必要がありますが、私たちのエネルギーは限られています。

そのため、JVM の原理については、現時点では理解できない、または使用できない知識ポイントがある場合は、一旦脇に置いておき、正確に学習することができます。節約したエネルギーを他の知識や自分の人生に使う方が有意義です。

これを読んで何か得られたと感じた方は、ぜひ転送したり、「読んでいます」ボタンをクリックしてください。あなたのサポートは私にとってとても重要です。

こんにちは、Siyuanwaiです。

上場企業のテクニカルディレクターとして、100 名を超える技術チームを管理しています。

私はコンピューターサイエンスを専攻していない卒業生からプログラマーに転向し、懸命に働きながら成長してきました。

この記事はWeChatの公開アカウント「Siyuanwai」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合はSiyuanwai公式アカウントまでご連絡ください。

<<:  FinOps: クラウドコスト管理の鍵

>>:  IBM、マルチクラウド プラットフォームで実行される AI モデル用の CodeFlare フレームワークをオープンソース化

推薦する

dogyun: 香港独立サーバー、即時起動+自己管理、300元/月、e5-2637v2/16g/480g/10M帯域幅

Dogyun は現在、香港の独立サーバーに割引を提供しています。すべての独立サーバーは月額 100 ...

1枚の写真で数十億のAmazon Web Services IoT接続のパワーを解き放つ

「東樹西軒」は人気を博し、そのプロジェクトはあまりにも大規模で、一般の人々には何の関係もないようです...

jollyworkshosting - Phoenix VPS が 50% オフ

Jollyworkshosting は、2009 年に VPS 事業を開始したフィリピンのインターネ...

キューブクラウド - 25元/CN2 GIA回線/ロサンゼルス/512Mメモリ/1Gメモリ/1Tトラフィック

Fengniao Technology 傘下のホスティング ブランドである CubeCloud は、...

サイトの縮小に伴う3つの主要な執行者を個人的に体験する

諺にあるように、世の中に生きていれば、必ず傷つくことになります。著者は 2 年間の最適化経験を持って...

Hosteons: 米国 VPS は年間 6 ドルから、メモリ 512M/コア 1 個/SSD 10g/トラフィック 1T/帯域幅 10Gbps

Hosteons は現在、年間 6 ドルという低価格で米国の VPS サービスを提供しています。デー...

現在および将来にわたってマルチクラウド プロジェクトを予算内で維持する方法

Rightscale は、「2017 年のクラウドの現状」レポートで、約 85% の組織がマルチクラ...

小玖同:オンラインとオフラインをリンクして広告主のマーケティングを支援するこのモデルは、将来の広告の新たなトレンドになるかもしれない

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますXiaoq...

dedipath - 6 ドル/5g メモリ/100g SSD/2 コア/5T トラフィック/2IP/ロサンゼルス

dedipath は最近設立されたホスティング ブランドのようです。現時点では、あまり情報がありませ...

記事の掲載が難しい状況に直面し、細部にもっと注意を払う必要がある

今年、百度のアルゴリズムが継続的に改善・調整されたため、自分のウェブサイトや友人のウェブサイトのコン...

垂直ソーシャルネットワーキング - ペットソーシャルネットワーキングは適切な市場を正確に位置づけ、見つけます

【ポイント】大規模で包括的なSNSはすべての人のニーズを満たすことは決してできないため、SNSの概念...

マイクロソフトがWindows 8の価格を発表、予約注文受付開始

テンセントテクノロジーニュース(潮汇)北京時間10月13日、海外メディアの報道によると、マイクロソフ...

特別版: BlueVM - 年間 5 ドルの VPS/年間 7 ドルの VPS

皆さんは bluevm をよくご存知だと思います。現在、特別版の VPS が 2 つあり、年間 5 ...

Baidu SEO における新たな現象: 内部ページランキングが完全に消えてしまったらどうすればいいでしょうか?

最近、多くのウェブマスターが、ウェブサイトの内部ページランキングが一夜にして消えてしまうという現象に...