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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JVM

JVM(Java Virtual Machine)があれば、一連のコンピューターソフトウェアプログラムとデータストラクチャが、仮想マシンモデルを使って他のコンピュータプログラムやスクリプトを拡張できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

キャスト

キャストとは、オブジェクトの型の変換が許可された場合に、明白に別の型への変換を行うプロセスのことです。

Q&A

解決済

6回答

2974閲覧

JVMは何を参考にメソッドを呼び出すか

rakkn

総合スコア6

JVM

JVM(Java Virtual Machine)があれば、一連のコンピューターソフトウェアプログラムとデータストラクチャが、仮想マシンモデルを使って他のコンピュータプログラムやスクリプトを拡張できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

キャスト

キャストとは、オブジェクトの型の変換が許可された場合に、明白に別の型への変換を行うプロセスのことです。

0グッド

2クリップ

投稿2020/05/30 05:19

編集2020/05/30 08:08

###前提
Java構文を知りたいわけではなく、JVMの内部実装を理解するのが目的です。
###実現したいこと

どのようにメソッドや変数が呼び出されるかを知る。またアップキャストによるインスタンスのヘッダの変化やロック情報の変化があるのかいなか。

該当のソースコード

java

1class AA{ 2 private int i; 3 4 public void hello(){ 5 System.out.println("Hello"); 6 } 7} 8class BB extends AA{ 9 private int j; 10 11 public void yeah(){ 12 System.out.println("Yeah!"); 13 } 14} 15 16class Test{ 17 public static void main(String[] args){ 18 AA aa = new AA(); 19 BB bb = new BB(); 20 21 aa.hello(); 22 23 aa = bb;//アップキャスト 24 25 aa.yeah();//コンパイルエラー 26 aa.i = 1;//コンパイルエラー 27 aa.j = 2;//コンパイルエラー 28 } 29}

### 質問

1. "aa.hello();"を実行する際、コンピュータは参照型変数"aa"自体の型を見て、その型のクラスにアクセスするのか、参照型変数"aa"の指し示す先のインスタンスのヘッダにある"このインスタンスはどこのクラスに属するものか"という情報を参考にクラスにアクセスするのか、はたまた別の方法なのかがわかりません。

2. アップキャスト時に、参照型変数"bb"の指し示す先のインスタンスのヘッダの情報は変更されるのでしょうか? また、変数などのロック情報も変更されるのでしょうか?

3. "aa.yeah()"でコンパイルエラーになるのはどうしてでしょうか? 質問1と質問2の内容を関連付けて説明していただけると助かります。

4. "aa.i"と"aa.j"が下記のようなエラーを発生させるのがなぜだかわかりません。こちらも質問1と質問2の内容に関連させて説明いただけると助かります。

 以上、全体を通してJVM上での動きを問う質問です。JVM上での動きに焦点を当てた回答をいただけると助かります。

###コンパイルエラー

Test.java:25: エラー: シンボルを見つけられません aa.yeah();//コンパイルエラー ^ シンボル: メソッド yeah() 場所: タイプAAの変数 aa Test.java:26: エラー: iはAAでprivateアクセスされます aa.i = 1; ^ Test.java:27: エラー: シンボルを見つけられません aa.j = 2; ^ シンボル: 変数 j 場所: タイプAAの変数 aa エラー3個

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2020/05/30 05:24

それがコンパイルエラーになるのはJavaの構文の問題です。JVMはほとんど関係がありません
rakkn

2020/05/30 05:32

キャストをしなければならないのはわかっているのですが、どのようなアクセス過程があったのかを知りたいのです。おわかりであればお教えください。
BluOxy

2020/05/30 05:34

すみません。「キャストをしなければならない」というのはどういうことでしょうか。 必要がなければキャストをしなくても良いと思います。 単純にキャストの仕組みが知りたいのですよね。であれば、それはJavaの言語仕様の問題であり、JVMは関係ないと思います。
rakkn

2020/05/30 05:43

すみません。「キャストをしなければならない」というのはどういうことでしょうか。 -> ((BB).aa).i のことをさしていたのですが間違いでしょうか? 単純にキャストの仕組みが知りたいのですよね。であれば、それはJavaの言語仕様の問題であり、JVMは関係ないと思います。  ->なるほど!キャストに関してはJVMは関係がないんですね!ありがとうございます。
BluOxy

2020/05/30 05:59

質問からそれてしまうので、あまり追及したくありませんが、**何が目的で** キャストをしなければならないのかが分からないという話をしています。 例えば、「Javaのコーディングをしていく中でキャストを理解する必要が出たから」のような理由であれば理解できます。
rakkn

2020/05/30 06:11

まさにその理由です。teratail初心者のため、そういった何が目的かを列挙する慣習があると知りませんでした。以後、気をつけて質問するように心がけます。
BluOxy

2020/05/30 06:18 編集

質問というのは、当然何か目的があってする訳ですよね。 色々な質問を見ている訳ですが、質問内容によっては「何が目的でこんな質問をしたんだろう。回答する必要はあるのだろうか」と思うことがあります。これは私だけではなく他のユーザーでも同じことがいえると思います。 なので、teratailにかかわらず、どこで質問するとしても目的を事前に伝えることは必要不可欠だと思います。(暗黙で目的が伝わる場合を除き)
rakkn

2020/05/30 06:23

なるほど、一応”前提・実現したいこと”の欄に記述しているのですが、目的不十分みたいですね。以後気をつけます。
BluOxy

2020/05/30 06:33 編集

なるほど。記述はしていらっしゃいますが、私はその記述から意図を組めませんでした。 もし他の方が組めていたのであれば、単に私が理解していなかっただけなので、そのときは申し訳ないです。 タイトルや前提・実現したいことが「キャストの仕様を理解したい」のような旨だと私なら意図が組めました。
rakkn

2020/05/30 06:38

質問1,2と3,4を2つに分けるべきでした。混乱を招いてしまい申し訳ございません。
BluOxy

2020/05/30 06:51 編集

私はそこが混乱の原因だとは思っていません。 どちらかというと、JVMが関係ないに関わらず、JVMの話が混ざっているのが話を難しくしていると思います。あとは、質問するに至った背景や目的が誰に対しても明確だとより答えやすい質問ではあったと思います。(質問は編集できるので、適宜してもらえればと思います) ただ、そのように情報を整理していくと、これは「Javaの言語仕様におけるキャストの仕組み」についての質問なので、「Java キャスト」「Java キャスト 言語仕様」「Java Casting Language Specification」などと調べていれば自己解決できたかもしれないという話にも繋がります。 要は、質問をする前に「質問を答えさせるのに必要な情報」が何かを整理すべきではあると思います。
rakkn

2020/05/30 07:23

具体的な指摘をありがとうございます。参考にさせていただきます。
quickquip

2020/05/30 07:35 編集

BluOxyさんに同意します。 1〜4すべて、Java言語仕様に関する質問であって、JVMには(JVM仕様にもJVM実装にも)関係ありません。 今の質問ですと「JVMと関係があると思っているのが間違い」はまったく妥当な回答かと思います。 質問が書き換わらないと、その方向で回答を補強すればいいのか、BluOxyさんの回答と同じく「言語仕様に関する」方向で回答を補強すればいいのか、迷うところです。
rakkn

2020/05/30 07:53

なるほど、ありがとうございます。
BluOxy

2020/05/30 07:57

もしかして、JVMの内部実装が知りたいのでしょうか?Javaの構文を学びたいのではなく。
rakkn

2020/05/30 08:01

その通りです。
BluOxy

2020/05/30 08:06 編集

やっと理解しました。JVMの内部実装を知りたい方がいるとは認識していなかったので、その可能性が隅にもありませんでした。 前提・実現したいことに「Javaの構文を学ぶことが目的ではなくJVMの内部実装を知ることが目的」と書いておいた方が良いと思います。私のような勘違いする人が出てくるので 3.4を分けるべきという意味も理解しました。コンパイルエラーが云々の質問はそれこそコンパイラの問題なので、消しておいて正解だと思います。
rakkn

2020/05/30 08:06

なるほど参考になります。
rakkn

2020/05/30 09:52

ご回答ありがとうございます。参考にしてみます!
guest

回答6

0

###まず第一に文法エラーが生じていますが、これは別問題とします。

JVMの内部動作を知りたいならばバイトコードレベルでないと議論になりません。コンパイル前のjavaで記された状態では議論できません。

投稿2020/05/30 09:47

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rakkn

2020/05/30 09:54

ご回答ありがとうございます。なるほど、そうなんですね。バイトコードについて掘り下げてみます。
guest

0

ベストアンサー

ちゃんとした回答ではないのですが、コードを書きたかったのでここで。

趣旨からするとコードは、

java

1class AA { 2 private int i; 3 4 public void hello() { 5 System.out.println("Hello"); 6 } 7} 8 9class BB extends AA { 10 private int j; 11 12 public void hello() { 13 System.out.println("Yeah!"); 14 } 15} 16 17public class Test { 18 public static void main(String[] args) { 19 AA aa = /* ☆1 →*/new AA(); 20 BB bb = /* ☆2 →*/new BB(); 21 22 aa.hello(); 23 24 aa = bb; /* ★1 */ 25 26 aa.hello(); 27 28 bb = (BB)aa; /* ★2 */ 29 30 bb.hello(); 31 } 32}

の方がいいと思うのですよね。(iもjも不要ですが手を付けず)

これをコンパイルした時のバイトコードをIntelliJ IDEAのShow byte codeの機能で見ると、

plain

1// class version 52.0 (52) 2// access flags 0x21 3public class Test { 4 5 // compiled from: Test.java 6 7 // access flags 0x1 8 public <init>()V 9 L0 10 LINENUMBER 17 L0 11 ALOAD 0 12 INVOKESPECIAL java/lang/Object.<init> ()V 13 RETURN 14 L1 15 LOCALVARIABLE this LTest; L0 L1 0 16 MAXSTACK = 1 17 MAXLOCALS = 1 18 19 // access flags 0x9 20 public static main([Ljava/lang/String;)V 21 L0 22 LINENUMBER 19 L0 23 NEW AA 24 DUP 25 INVOKESPECIAL AA.<init> ()V 26 ASTORE 1 27 L1 28 LINENUMBER 20 L1 29 NEW BB 30 DUP 31 INVOKESPECIAL BB.<init> ()V 32 ASTORE 2 33 L2 34 LINENUMBER 22 L2 35 ALOAD 1 36 INVOKEVIRTUAL AA.hello ()V 37 L3 38 LINENUMBER 24 L3 39 ALOAD 2 40 ASTORE 1 41 L4 42 LINENUMBER 26 L4 43 ALOAD 1 44 INVOKEVIRTUAL AA.hello ()V 45 L5 46 LINENUMBER 28 L5 47 ALOAD 1 48 CHECKCAST BB 49 ASTORE 2 50 L6 51 LINENUMBER 30 L6 52 ALOAD 2 53 INVOKEVIRTUAL BB.hello ()V 54 L7 55 LINENUMBER 31 L7 56 RETURN 57 L8 58 LOCALVARIABLE args [Ljava/lang/String; L0 L8 0 59 LOCALVARIABLE aa LAA; L1 L8 1 60 LOCALVARIABLE bb LBB; L2 L8 2 61 MAXSTACK = 2 62 MAXLOCALS = 3 63 64

でした。(OpenJDK 11使用)

アップキャスト(ソースコードの★1、バイトコードのL3)は、コンパイル時点で"必ず成功する"と判明しているので、bbの変数の内容(=☆2のインスタンスのアドレス)を、aaに書き込んでいるだけで終わり。

ダウンキャスト(ソースコードの★2、バイトコードのL5)は、aaの変数(=この時点では☆2のインスタンスのアドレス)が指している先をBBにキャスト出来るかどうかチェックするCHECKCAST命令が間に入っているという違いがあります。その後aaの変数の中身(=☆2のインスタンスのアドレス)をbbに書き込んでます。

CHECKCAST命令の仕様は
https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-6.html#jvms-6.5.checkcast
ですが、参照先(=☆2のインスタンスのアドレス)を書き換える必要があるとはちょっと思えないです。


バイトコードを読み取って命令の仕様に則って動けばいいのであって、"各命令の実装"がどうあるべきかはJVM仕様には載っていません。
"各命令の実装"をどうするかはJVMを作る人に任されているわけで、そこは実装を読むしかないと思います。

それを読むにはC++の知識が要りますが、しかしC++の知識がそこそこあるなら、仮想関数テーブルなどにもなじみがあるはずで、こんな質問が出てくることはないだろうと思います。

このような質問が出てくる → 仮想関数テーブルのような知識がない → 言語実装やC++になじみがない → ちゃんとした回答が出てもたぶんわからない
と想像しています。

もっと一般的な言語実装の方の勉強で、ポリモーフィズムをどう実装するのか(仮想関数テーブルがその例)という線で理解を進めた方が結局近道かと思います。

投稿2020/05/30 09:38

quickquip

総合スコア11235

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rakkn

2020/05/30 10:19

ご回答ありがとうございます。非常に噛み砕いた説明で分かりやすかったです!このような疑問はバイトコードを用いて実装を見てあげれば解決するんですね!しょうもない質問に時間を割いていただき誠にありがとうございます。
Zuishin

2020/05/30 10:24

> バイトコードを読み取って命令の仕様に則って動けばいいのであって、"各命令の実装"がどうあるべきかはJVM仕様には載っていません。 これを読んでの感想がそれですか?
rakkn

2020/05/30 10:40

勘違いしていました。バイトコードの実装方法はJVMによって異なるため、実際の実装を確認するしかないが、そもそも仮想関数テーブルに関する知識が無いために実装を読んでも理解出来ない。だから、quiquiさんの言う通りポリフォーフィズムについて見識を深めるべき、ということですね。ご指摘ありがとうございます。
quickquip

2020/05/30 10:43

> このような疑問はバイトコードを用いて実装を見てあげれば解決するんですね! いいえ。それができるならこのような疑問はありえないでしょう。 疑問はまっとうなものだと思いますが、この疑問をJavaVMのコードを読んで解決しようとするのはあまりにも無謀です。 という意味で「ちゃんとした回答」ではないという趣旨です。
quickquip

2020/05/30 10:43

かぶりました。
quickquip

2020/05/30 10:47

> バイトコードの実装方法 "バイトコードを実行する部分の実装方法"ですね。(意図は伝わっていると思いますが) はい。そういう趣旨の回答です。
rakkn

2020/05/30 12:31

ご指摘ありがとうございます。言葉足らずですみません。改めて、ありがとうございます!
guest

0

直接的な回答ではないですが、基本的にプログラミングの話題のサイトなので
集まる人でJVMの実装を知る人は少ないと思います。

https://openjdk.java.net/

こちらでソースコードを見てはいかかでしょうか。

こちらのスレッドではOpenJDK以外のJVMのソースコードの場所も提示されてました
※リンク先が生きてるかは未確認ですが

https://stackoverflow.com/questions/2026093/is-jvm-open-source-code

投稿2020/05/30 09:24

momon-ga

総合スコア4826

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rakkn

2020/05/30 10:00

ご回答ありがとうございます。まだJAVAプログラミングを始めたばかりなのでJVMのソースコードを見てもわからないかと... でも、そのような解決方法もあるのだと言うことがわかりました!ありがとうございます!
guest

0

それ等がコンパイルエラーになるのはJavaの構文の問題です。JVMはほとんど関係がありません。

"aa.hello();"を実行する際、コンピュータは参照型変数"aa"自体の型を見て、その型のクラスにアクセスするのか

aaの型はAAなので、AAクラスに定義されているhelloメソッドを呼び出しています。
型をチェックしているのはJavaのコンパイラであり、実際にそのクラスのインスタンスにアクセスしているのはコンパイルされたJavaのプログラムです。

アップキャスト時に、参照型変数"bb"の指し示す先のインスタンスのヘッダの情報は変更されるのでしょうか? また、変数などのロック情報も変更されるのでしょうか?

インスタンスのヘッダ情報 とは何でしょうか。変数のロック情報という言葉も聞いたことがありません。
なので、投げ遣りな回答かもしれませんが、それ等を気にする必要はありません。
※個人的には上記のワードの出典が気になるので、教えて頂きたいです

"aa.yeah()"でコンパイルエラーになるのはどうしてでしょうか? 質問1と質問2の内容を関連付けて説明していただけると助かります。

aaの型はAAなので、AAクラスに定義されていないyeahメソッドは実行できません。

"aa.i"と"aa.j"が下記のようなエラーを発生させるのがなぜだかわかりません。こちらも質問1と質問2の内容に関連させて説明いただけると助かります。

AAクラスに定義されているフィールドiのアクセス修飾子がprivateだからであり、privateなフィールドはクラスの外からアクセスすることができません。

jに関してはAAクラスに定義されておらず、privateでもあるので、同様にアクセスすることができません。

投稿2020/05/30 05:38

編集2020/05/30 05:50
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rakkn

2020/05/30 06:07

ご回答いただきありがとうございます。誠に無礼な発言をお許しください。私の文章能力が低いためか、回答者さんは質問の意図を理解されていないようです。再度、ご精読されて、おわかりであればご回答よろしくお願いします。 aaの型はAAなので、AAクラスに定義されていないhelloメソッドは実行できません。 -> helloメソッドはAAクラスで定義されているので実行できると思うのですが... インスタンスのヘッダ情報 とは何でしょうか。変数のロック情報という言葉も聞いたことがありません。 なので、投げ遣りな回答かもしれませんが、それ等を気にする必要はありません。  ->https://www.slideshare.net/KiyokuniKawachiya/java-66003903?from_action=save の38ページあたりに記載されてます。私の表現が適切でないために理解を得られなかったのかもしれません。
BluOxy

2020/05/30 06:32 編集

誤解を招いてすみません。編集前の回答は誤りですので、「helloメソッドはAAクラスで定義されているので実行できる」はその通りです。ブラウザの更新で編集後の回答を確認してください。
BluOxy

2020/05/30 06:56 編集

タイトルにJava仮想マシンの実装技術と書いてあります。Javaのコーディングが目的であれば、Javaの言語仕様を知るべきで、JVMの内部実装は知る必要がありません。(とはいえ、JVMの役割・機能自体は知っておくべきです)
BluOxy

2020/05/30 06:39

恐らく、Java でコーディングしている方々の大半はそのスライドの内容を知らないと思います。通常のコーディングでは知る必要性がないので。Javaのメモリ事情を調査した人なら知っているかもしれませんが。
BluOxy

2020/05/30 07:34

すみません。普通にスルーしていましたが、私は質問の意図を理解できていないでしょうか。 1~4の質問に対して、JVMは関係ないと明示した上で回答したつもりです。
rakkn

2020/05/30 07:58 編集

先程、https://docs.oracle.com/javase/specs/jvms/se7/html/ を確認したところ、"Invoking Methods"に質問1の説明が載っていました。3,4に関しては素直に覚えるようにします。大変ご迷惑をお掛けし、申し訳ございませんでした。
guest

0

JVM上での動きに焦点を当てた回答をいただけると助かります。

無理です。コンパイルエラーはコンパイラが発するものであり、JVMで実行するより前の段階で発生するものです。

投稿2020/05/30 05:38

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/05/30 05:44

Javaの言語仕様とJVMの仕様は(関連はあるものの)別物です。
rakkn

2020/05/30 06:17

ご回答ありがとうございます。では、質問文ではjavaの言語仕様に関する質問とすればよろしかったのですね。
guest

0

この記事が参考になるかもしれません。
私の知りたかった本質的な部分がここに載っているので参考になれば。尚、質問内容とは一切関係のないことにご留意ください。

https://qiita.com/RYO-4947123/items/eaeb48b6fcf97c02710f

投稿2020/05/31 01:53

編集2020/05/31 04:50
rakkn

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2020/05/31 04:42 編集

なぜそう思いました? これは文法レベルの話で、複数の回答にあるように、質問とは無関係ですが。 vtable どうこうより前に、コンパイラと VM の区別をつける必要があると思います。
rakkn

2020/05/31 04:46

私の知りたかった本質的な部分がこれと一致していたので。本質的な部分についてはここの質問には明記していませんでしたので誤解を招いたかもしれません。ご指摘ありがとうございます。
Zuishin

2020/05/31 04:50

知りたいことがこれと一致していたということは、 > Java構文を知りたいわけではなく、JVMの内部実装を理解するのが目的です。 質問のこの部分が完全に間違っていたということになりますが? 繰り返しになりますが、リンク先の記事は JVM の内部実装とは全く無関係に、Java の構文について書かれています。 用語が正しく無ければ正しく質問できないので、まずは入門書から始めることを強くお勧めします。回答者の多くが混乱しています。
rakkn

2020/05/31 05:00

質問のこの部分が完全に間違っていたということになりますが? >Javaを理解するためのアプローチの一つだと思っていただければよいと思います。 用語が正しく無ければ正しく質問できないので、まずは入門書から始めることを強くお勧めします。回答者の多くが混乱しています。 >おっしゃるとおりです。 vtable どうこうより前に、コンパイラと VM の区別をつける必要があると思います。 >おっしゃるとおりです。質問した時点ではなんとなくの区別で認識していました。ご回答者方には非常にご迷惑をおかけしたと感じております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問