質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

クラスオブジェクト(側)のメモリ領域の情報には「静的フィールド・静的メソッド」も入る?

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 4,309

mr0237

score 162

JAVAを勉強している者です。説明が下手で、さらにすっきりしない質問ですいませんが、この質問のコメント欄に

おおまかにいえばnew側で確保されたメモリ領域には以下が入ってます。

(A)そのインスタンスのクラスオブジェクト(クラス型)への参照(メモリ領域のアドレス情報)
(B)そのインスタンスの属性

なお、(A)はこのインスタンスに対してgetClass()メソッドを呼び出すと取り出せるクラスオブジェクト(クラス型)の参照(メモリ領域のアドレス情報)が入ってます。そのクラスオブジェクト(クラス型)の中にメソッドの情報が入っているという具合です。

と書かれていたのですが「スッキリわかるJava入門 第2版 (スッキリシリーズ) 」の(P367)「静的メソッド」のところを復習を兼ねて読み直してみると、

メソッド自体がクラスに属するようになる。

静的メソッドは、その実体が各インスタンスではなくクラスに属し、「クラス名.メソッド名();」で呼び出せるようになります。

と書かれていたのですが、これってつまり、

クラスオブジェクト側(例:Hero型の変数h)で確保されたメモリ領域って以下の情報が入っているのでしょうか?

・newで属性を入れるための領域が確保された先頭アドレスの情報
・操作の情報
・静的フィールド・静的メソッドの情報

↑これらの情報が入っているのでしょうか?

(↑ちょっと自分でも混乱してしまう可能があるので自分なりのわかりやすい言葉(例:「クラスオブジェクト」→「クラス型」)で書いてしまいました。すいません。)

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

javaの技術書のほとんどには、javaのソースは中間マシン(JVM)で動作し、JVMが実行環境毎の差分の吸収とメモリ管理を引き受けることが書いてあると思います。

メモリ管理を自動で行う点は、javaを作る際に参考にしているC++との大きな差で利点であると同時に、その動きはプログラマにが意識しずらいという問題を抱えています。

そして、javaのメモリに関する話は中間コードやJVMのレベルの解説書以外で書かれれている場合は基本的にはたとえ話です。

実際の動きを確かめるコードを書きました。実行してみてください。

public class ClassA{
    public static int a = ClassA.makeA();
    public static int b = ClassA.makeB();
    public static int makeA(){
        System.out.println("makeA");
        return 1;
    }

    public static int makeB(){
        System.out.println("makeB");
        return 1;
    }

    // クラス変数は不要のメソッド
    public static int getC(){
        System.out.println("makeC");
        return 1;
    }

    // 空のコンストラクタ
    public ClassA(){}
    public int d = makeD();
    public int e = makeE();

    public int makeD(){
        System.out.println("makeD");
        return 1;
    }

    public int makeE(){
        System.out.println("makeE");
        return 1;
    }
 }


クラス変数a,b及びインスタンス変数d,eのメモリが確保されたタイミングでログを書き出すようにクラスの定義をしています。

そして、クラスメソッドgetCは、クラス変数もインスタンス変数も不要です。

この状態でgetCを呼び出してみました。

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("test");
        System.out.println("ClassA.getC:" + ClassA.getC());
    }
}

私がテストした環境では、出力はこのようになりました。

test
makeA
makeB
makeC
ClassA.getC:1

クラス変数の領域を確保してから、クラスメソッドを実行しています。
ポイントとしては、クラス変数a,b両方とも確保している点です。絶対とは言い切れませんが、一度にすべての変数の領域を確保していることがわかると思います。

また、"test"が先に表示されていますので、ClassAのクラスメソッドが初めて実行されるタイミングで領域の確保が行われるという点がわかります。

次に、インスタンスを作ったときのテストをします。

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("test");
        ClassA a = new ClassA();
    }
}

私の環境ではこのようになりました。

test
makeA
makeB
makeD
makeE

インスタンスを作ったタイミングで、クラス変数の領域も(必要ないのに)確保されました。

このように、実際にテストするとなんとなくイメージがつかめるのではないでしょうか?いろいろためしてみてください。

ところで、バージョンによって全然違う動きをする可能性もあり、ここらへんは現段階ではあまり突っ込まなくても問題がないとは思いませんか?(本の方でお茶を濁しているのも一理あるとおもいます。)

ソースはこちらです。
https://paiza.io/projects/8W5ex0OgDSri8c4mte4JQA

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/04 12:22

    じゃあつまり、(何度も繰り返してすいません。)クラスオブジェクト側(例:Hero型の変数h)で確保されたメモリ領域ってやはり、以下の情報が入っているのでしょうか?

    ・newで属性を入れるための領域が確保された先頭アドレスの情報
    ・操作の情報
    ・静的フィールド・静的メソッドの情報

    ↑これらの情報が入っているのでしょうか?

    キャンセル

  • 2017/05/04 21:36

    そこら辺は正確な話は出来ません。
    JVMのマニュアルを読むべき内容です。
    (そして、まだあなたはJVMのマニュアルを読む段階に無いと思います。)

    ただ、クラス変数は、インスタンスが存在しない場合ははじめて呼び出された段階でメモリに領域の確保がされるらしい。インスタンス変数、クラス変数ともに変数はまとめて確保されることが上記のテストによって確認ました。

    ここから、メモリの連続領域に取られてているっぽいという点を理解しておく程度に留めて置くべきだと思います。

    どうしても、その点を理解したければメモリ管理が自動化されていない言語(アセンブラやC++が代表的?)でどのようにメモリを管理すると効率的なプログラムが組めるかを理解する必要があります。

    というわけで、せっかくjavaが隠してハードルを下げている部分には踏み込まず、まずjavaの基本的な文法を覚える事を先行させたほうが良いと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Javaに関する質問
  • クラスオブジェクト(側)のメモリ領域の情報には「静的フィールド・静的メソッド」も入る?