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

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

ただいまの
回答率

90.34%

  • C#

    7685questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • C

    3977questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3759questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

プロセスのメモリ検索の質問です

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 565

masayukasina

score 3

 前提・実現したいこと

下記はソースの1部分なんですが、あるプロセスのメモリを検索しています。00000000~7FFFFFFFまでを検索しているのですが7FFFFFFFを9FFFFFFFまでに増やしたいです、単純に終了アドレスを9FFFFFFFにしても検索してくれないですが何故でしょうか?

 発生している問題・エラーメッセージ

7FFFFFFF以上を検索してくれません

 該当のソースコード

c++
UINT search_1(HANDLE hProcess, unsigned char bytecode[], int n, UINT and1, int intAnd1, UINT and2, int intAnd2) {
    TNtReadVirtualMemory pfnNtReadVirtualMemory = NULL;
    pfnNtReadVirtualMemory = (TNtReadVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtReadVirtualMemory");

    TNtWriteVirtualMemory pfnNtWriteVirtualMemory = NULL;
    pfnNtWriteVirtualMemory = (TNtWriteVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtWriteVirtualMemory");
    MEMORY_BASIC_INFORMATION mBI;
    // サーチ開始アドレス
    UINT start = 0x00000000;
    // サーチ終了アドレス
    UINT end = 0x7FFFFFFF;
    int a = 0;
    int b = 0;
    __int64 b_0 = 0;
    __int64 b_1 = 0;
    __int64 b_2 = 0;
    __int64 b_3 = 0;
    __int64 b_4 = 0;
    __int64 b_5 = 0;
    int r_11 = 11;
    int r_8 = 8;
    int addr1 = 0;
    int addr2 = 0;
    int addr2_0 = 0;
    int addr2_1 = 0;
    int addr2_2 = 0;
    int addr2_3 = 0;
    int addr2_4 = 0;
    int addr2_5 = 0;

    int intActionCnt = 0;

    while (start < end) {
        SIZE_T size = VirtualQueryEx(hProcess, (void*)start, &mBI, sizeof(MEMORY_BASIC_INFORMATION));

        if (size == 0) {
            std::cout << "error" << std::endl;
            break;
        }

        if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE) && (mBI.Type != MEM_IMAGE)) {
            UINT start2, end2;
            start2 = start;
            end2 = start2 + mBI.RegionSize;
            int p;
            CHAR *MemoryBuff = new CHAR[4096];
            while (start2 <= end2)
            {
                pfnNtReadVirtualMemory(hProcess, (LPVOID)start2, (LPVOID)MemoryBuff, 4096, NULL);
                for (p = 0; p < 4096; p++)  //バッファのサイズ=ループ回数
                {
                    start2++;
                    MemoryBuff++;
                    if (memcmp(MemoryBuff, bytecode, n) == 0) {
                        //cout << "address=" << hex << start2 << "\n";

                        //addr2_0 = start2 + 0x5c;
                        addr2_1 = start2 + 0x68;
                        addr2_2 = start2 + 0x18;
                        addr2_3 = start2 + 0x10;
                        addr2_4 = start2 + 0x14;
                        //addr2_5 = start2 - 0x8;
                        //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_0, &b_0, 4, NULL);
                        pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_1, &b_1, 4, NULL);
                        pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_2, &b_2, 4, NULL);
                        pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_3, &b_3, 4, NULL);
                        pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_4, &b_4, 4, NULL);
                        //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_5, &b_5, 4, NULL);

                        if (b_1 == 2 && b_2 == 383558760 && b_3 == 0 && b_4 == 0) {
                            cout << "address1=" << hex << start2 << "\n";
                            pfnNtWriteVirtualMemory(hProcess, (LPVOID)addr2_1, &r_8, 4, NULL);
                            //return start2;
                        }
                    }
                }
                MemoryBuff = MemoryBuff - 4096; //ポインタを戻しておきます。

            }

        }
        start += mBI.RegionSize;
    }
    return 0;
}

 試したこと

ここに問題に対して試したことを記載してください。

 補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • a_saitoh

    2018/06/14 16:22

    「探索してくれません」とはどのような症状が出て探索してくれないと判断したのでしょうか?

    キャンセル

  • masayukasina

    2018/06/14 16:45

    cout << "address=" << hex << start2 << "\n"; で表示させても7FFFFFFFF以上は検索してないんです。

    キャンセル

  • a_saitoh

    2018/06/14 18:02

    どういう症状から検索できてないと判断できたのでしょう?

    キャンセル

回答 3

checkベストアンサー

+1

    int addr1 = 0;
    int addr2 = 0;
    int addr2_0 = 0;
    int addr2_1 = 0;
    int addr2_2 = 0;
    int addr2_3 = 0;
    int addr2_4 = 0;
    int addr2_5 = 0;

とりあえずコレをuintに変更すべき

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/14 11:20

    ありがとうございます。
    ソースのint をunitに変更するだけでしょうか?まだまだ覚えたての素人でして…
    ちなみにCheatEngineの様なメモリエディターで内部を検索すると7FFFFFFF以上に目的の値が出てきます、それを検索したいのですが難しいでしょうか?

    キャンセル

  • 2018/06/14 13:25

    > ソースのint をunitに変更するだけでしょうか?
    そうですね
    実際に動かしたわけじゃないので、これで充分かはわかりませんが

    > 難しいでしょうか?
    コードを精査してゆっくりデバッグしていけば不可能ではないと思いますよ

    キャンセル

  • 2018/06/14 13:38

    'uint': 定義されていない識別子です。
    構文エラー: ';' が、識別子 'addr1' の前に必要です。
    が出ます(・_・;)

    キャンセル

  • 2018/06/14 13:42

    んじゃ、unsigned int か UINTで

    キャンセル

  • 2018/06/14 14:01

    int addr1 = 0;
    int addr2 = 0;
    int addr2_0 = 0;
    int addr2_1 = 0;
    int addr2_2 = 0;
    int addr2_3 = 0;
    int addr2_4 = 0;
    int addr2_5 = 0;
    この部分だけintをUINTにするとエラーが出なくなりましたがひたすらループして次に進まなくなりました。

    キャンセル

  • 2018/06/14 16:40

    うーん、あと問題になりそうなのは
    > start += mBI.RegionSize;
    ここだろうか
    mBI.RegionSizeが0だった場合(存在しうるかはしらん)無限ループすることになる。
    0だったら適当に1KBくらい飛ばしとけばいいのではないだろうか

    キャンセル

  • 2018/06/14 16:51

    start += mBI.RegionSize + 1;
    ということですか?

    キャンセル

  • 2018/06/14 17:05

    start += !mBI.RegionSize ? 1024 : mBI.RegionSize;

    かな

    キャンセル

  • 2018/06/14 18:02

    ありがとうございます、今晩試してみます。

    キャンセル

  • 2018/06/14 18:44

    ありがとうございます、下記のように変更するとFFFFFFFFまで検索するのですが検索が終わるとループ(最後でずっと同じ処理をしていて終了しない)するのですが何が原因でしょうか?
    UINT search_1(HANDLE hProcess, unsigned char bytecode[], int n, UINT and1, int intAnd1, UINT and2, int intAnd2) {
    TNtReadVirtualMemory pfnNtReadVirtualMemory = NULL;
    pfnNtReadVirtualMemory = (TNtReadVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtReadVirtualMemory");

    TNtWriteVirtualMemory pfnNtWriteVirtualMemory = NULL;
    pfnNtWriteVirtualMemory = (TNtWriteVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtWriteVirtualMemory");
    MEMORY_BASIC_INFORMATION mBI;
    // サーチ開始アドレス
    UINT start = 0x00000000;
    // サーチ終了アドレス
    UINT end = 0xFFFFFFFF;
    unsigned int a = 0;
    unsigned int b = 0;
    __int64 b_0 = 0;
    __int64 b_1 = 0;
    __int64 b_2 = 0;
    __int64 b_3 = 0;
    __int64 b_4 = 0;
    __int64 b_5 = 0;
    unsigned int r_11 = 11;
    unsigned int r_8 = 8;
    unsigned int addr1 = 0;
    unsigned int addr2 = 0;
    unsigned int addr2_0 = 0;
    unsigned int addr2_1 = 0;
    unsigned int addr2_2 = 0;
    unsigned int addr2_3 = 0;
    unsigned int addr2_4 = 0;
    unsigned int addr2_5 = 0;

    unsigned int intActionCnt = 0;

    while (start < end) {
    SIZE_T size = VirtualQueryEx(hProcess, (void*)start, &mBI, sizeof(MEMORY_BASIC_INFORMATION));

    if (size == 0) {
    std::cout << "error" << std::endl;
    break;
    }

    if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE) && (mBI.Type != MEM_IMAGE)) {
    UINT start2, end2;
    start2 = start;
    end2 = start2 + mBI.RegionSize;
    int p;
    CHAR *MemoryBuff = new CHAR[4096];
    while (start2 <= end2)
    {
    pfnNtReadVirtualMemory(hProcess, (LPVOID)start2, (LPVOID)MemoryBuff, 4096, NULL);
    for (p = 0; p < 4096; p++) //バッファのサイズ=ループ回数
    {
    start2++;
    MemoryBuff++;
    if (memcmp(MemoryBuff, bytecode, n) == 0) {
    //cout << "address=" << hex << start2 << "\n";

    //addr2_0 = start2 + 0x5c;
    addr2_1 = start2 + 0x68;
    addr2_2 = start2 + 0x18;
    addr2_3 = start2 + 0x10;
    addr2_4 = start2 + 0x14;
    //addr2_5 = start2 - 0x8;
    //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_0, &b_0, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_1, &b_1, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_2, &b_2, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_3, &b_3, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_4, &b_4, 4, NULL);
    //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_5, &b_5, 4, NULL);

    if (b_1 == 2 && b_2 == 383558760 && b_3 == 0 && b_4 == 0) {
    cout << "address1=" << hex << start2 << "\n";
    pfnNtWriteVirtualMemory(hProcess, (LPVOID)addr2_1, &r_8, 4, NULL);
    //return start2;
    }
    }
    }
    MemoryBuff = MemoryBuff - 4096; //ポインタを戻しておきます。

    }

    }
    start += mBI.RegionSize;
    }
    return 0;
    }

    キャンセル

  • 2018/06/14 19:17

    あー、オーバーフローしちゃいますね。

    start += mBI.RegionSize;

    start = std::numeric_limits<UINT>::max() - start < mBI.RegionSize ? std::numeric_limits<UINT>::max() : start + mBI.RegionSize;

    に変更して
    #include<limits>
    を冒頭へ挿入

    キャンセル

  • 2018/06/14 19:57

    ありがとうございます、ビルドエラーの原因はなんですかね?
    : warning C4003: マクロ 'max' に指定された実引数の数が少なすぎます。
    : error C2589: '(': スコープ解決演算子 (::) の右側にあるトークンは使えません。
    : error C2062: 型 'unknown-type' は不要です。
    これが出ます(泣)
    1: error C2059: 構文エラー: ')'
    UINT search_1(HANDLE hProcess, unsigned char bytecode[], int n, UINT and1, int intAnd1, UINT and2, int intAnd2) {
    TNtReadVirtualMemory pfnNtReadVirtualMemory = NULL;
    pfnNtReadVirtualMemory = (TNtReadVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtReadVirtualMemory");

    TNtWriteVirtualMemory pfnNtWriteVirtualMemory = NULL;
    pfnNtWriteVirtualMemory = (TNtWriteVirtualMemory)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtWriteVirtualMemory");
    MEMORY_BASIC_INFORMATION mBI;
    // サーチ開始アドレス
    UINT start = 0x00000000;
    // サーチ終了アドレス
    UINT end = 0xFFFFFFFF;
    unsigned int a = 0;
    unsigned int b = 0;
    __int64 b_0 = 0;
    __int64 b_1 = 0;
    __int64 b_2 = 0;
    __int64 b_3 = 0;
    __int64 b_4 = 0;
    __int64 b_5 = 0;
    unsigned int r_11 = 11;
    unsigned int r_8 = 8;
    unsigned int addr1 = 0;
    unsigned int addr2 = 0;
    unsigned int addr2_0 = 0;
    unsigned int addr2_1 = 0;
    unsigned int addr2_2 = 0;
    unsigned int addr2_3 = 0;
    unsigned int addr2_4 = 0;
    unsigned int addr2_5 = 0;

    unsigned int intActionCnt = 0;

    while (start < end) {
    SIZE_T size = VirtualQueryEx(hProcess, (void*)start, &mBI, sizeof(MEMORY_BASIC_INFORMATION));

    if (size == 0) {
    std::cout << "error" << std::endl;
    break;
    }

    if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE) && (mBI.Type != MEM_IMAGE)) {
    UINT start2, end2;
    start2 = start;
    end2 = start2 + mBI.RegionSize;
    int p;
    CHAR *MemoryBuff = new CHAR[4096];
    while (start2 <= end2)
    {
    pfnNtReadVirtualMemory(hProcess, (LPVOID)start2, (LPVOID)MemoryBuff, 4096, NULL);
    for (p = 0; p < 4096; p++) //バッファのサイズ=ループ回数
    {
    start2++;
    MemoryBuff++;
    if (memcmp(MemoryBuff, bytecode, n) == 0) {
    cout << "address=" << hex << start2 << "\n";

    //addr2_0 = start2 + 0x5c;
    addr2_1 = start2 + 0x68;
    addr2_2 = start2 + 0x18;
    addr2_3 = start2 + 0x10;
    addr2_4 = start2 + 0x14;
    //addr2_5 = start2 - 0x8;
    //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_0, &b_0, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_1, &b_1, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_2, &b_2, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_3, &b_3, 4, NULL);
    pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_4, &b_4, 4, NULL);
    //pfnNtReadVirtualMemory(hProcess, (LPVOID)addr2_5, &b_5, 4, NULL);

    if (b_1 == 2 && b_2 == 383558760 && b_3 == 0 && b_4 == 0) {
    cout << "address1=" << hex << start2 << "\n";
    pfnNtWriteVirtualMemory(hProcess, (LPVOID)addr2_1, &r_8, 4, NULL);
    //return start2;
    }
    }
    }
    MemoryBuff = MemoryBuff - 4096; //ポインタを戻しておきます。

    }

    }
    start = std::numeric_limits<UINT>::max() - start < mBI.RegionSize ? std::numeric_limits<UINT>::max() : start + mBI.RegionSize;
    }
    return 0;
    }

    キャンセル

  • 2018/06/14 20:23

    宜しくおねがいしますm(__)m

    キャンセル

  • 2018/06/14 20:35

    min maxがwindows.hで衝突してるのか・・・
    そんじゃ最大値使わずにやるか

    start = end - start < mBI.RegionSize ? end : start + mBI.RegionSize;

    キャンセル

  • 2018/06/14 21:11

    有難う御座います、完璧です。
    師匠と呼ばせていただきますm(__)m

    キャンセル

+1

OSが書いていないので推測ですが、32bit OS を使用していますでしょうか?

であれば、ユーザープロセスに割り当てられるメモリ領域の上限は一般的に 2GB なので、0x7fffffff までになるのはおかしくありません。
※上位側2GB はシステム用に予約される

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/14 10:38

    ありがとうございます、OSはWindow8.1の64Bitです。
    プロセスはNox AppというAndroidエミュレータです、その中のメモリを検索しています。

    キャンセル

  • 2018/06/14 10:59

    動作させているアプリが 32bit アプリならば、最大2GBの制限はついて回ります。
    Nox APP は 32bit アプリのようですね。

    キャンセル

  • 2018/06/14 11:19

    ありがとうございます。
    ちなみにCheatEngineの様なメモリエディターで内部を検索すると7FFFFFFF以上に目的の値が出てきます、それを検索したいのですが難しいでしょうか?

    キャンセル

  • 2018/06/14 18:08

    上でも書いていますが、0x7fffffff より大きなアドレスは、システム用の領域です。ですからそこに目的の値があったとしても、それが目的のデータである可能性は低いです。

    キャンセル

  • 2018/06/14 19:00

    ありがとうございます、何とか検索は出来るようになりましたが処理が終わらなくなってる状態です。

    キャンセル

+1

こんにちは。

Nox Appについては把握していませんが、該当のソース・コードをコンパイルしているコンパイラも恐らくint型は4バイトではないでしょうか?(PC上の多くの処理系がこのようになっています。)
その場合、int型で表現できる最大値は0x7fffffffです。


この手の仮想OSが絡む話の場合は、masayukasinaさんのコードがどこで走るコードなのかも明記しましょう。ゲストOSなのかホストOSなのかで回答が変わる場合もあります。
コンパイラの情報も記載しましょう。コンパイラによって状況が異なる場合もありがちです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/14 11:19

    ありがとうございます、コンパイラはVisual Studio 2017を使用しています。
    ちなみにCheatEngineの様なメモリエディターで内部を検索すると7FFFFFFF以上に目的の値が出てきます、それを検索したいのですが難しいでしょうか?

    キャンセル

  • 2018/06/14 11:30

    アドレスを保持する変数を0x7fffffffを超える値も保持できる型へ変更すればできる可能性があります。
    確実なのは、unsigned long longです。これは64ビット符号なしです。
    他に、masayukasinaさんのアプリを64ビットビルドする必要もあります。32ビットビルドですとアドレスは32ビットしか扱えません。

    キャンセル

  • 2018/06/14 13:39

    unsigned long long
    の使用法がわからないです、すいませんm(__)m

    キャンセル

  • 2018/06/14 13:46

    アドレスを保持している変数(addr1など)を unsigned long long型へ変えるだけですよ。

    キャンセル

  • 2018/06/14 14:02

    例えばどの部分をどのように変更すればいいのでしょうか?

    キャンセル

  • 2018/06/14 16:29

    そこまで回答すると丸投げに該当しそうです。C言語の変数宣言について調べてみて下さい。がんばです。

    キャンセル

  • 2018/06/14 18:59

    ありがとうございます、がんばります。

    キャンセル

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

  • C#

    7685questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • C

    3977questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3759questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。