web-dev-qa-db-ja.com

Java-Xmx1Gは10 ^ 9または2 ^ 30バイトを意味しますか?

そして、一般的に、-Xmx-Xms、および-Xmnオプションに使用される単位です(「k」、「M」、「G」、またはあまり標準的でない可能性「K」、 "m"または "g") バイナリプレフィックス 倍数(つまり、1024の累乗)、または1000の累乗ですか?

マニュアルには、キロバイト(kB)、メガバイト(MB)、ギガバイト(GB)を表すと記載されており、元の [〜#〜] si [〜#〜で定義されている1000の累乗であることが示唆されています。 ] システム。私の非公式のテスト(私はあまり自信がありません)は、それらが本当に kibibytes(kiB)mebibytes(MiB)/であることを示唆しています および ギビバイト(GiB) 、すべて1024の累乗。

それで、どちらが正しいですか?例えば。どのJavaコードは現在のサイズを表示しますか?

RAMサイズの場合、1024の倍数を使用することは驚くべきことではありません。これは、RAMは通常、ハードウェアモジュールを2倍にすることによって物理的にレイアウトされるためです。ただし、明確で標準的な単位を使用する混乱の可能性が高まるため、パワーが大きくなるにつれて、方法はますます重要になります。単位「t」は私のJVMでも受け入れられ、1TiBは1TBよりも10%大きくなります。

注:これらが実際に2進数の倍数である場合は、「」のような例を使用して、ドキュメントとユーザーインターフェイスを更新して非常に明確にすることをお勧めします。文字kまたはKを追加して、キビバイト(1024バイト)を示します。 、またはmまたはMは、メビバイト(1048576バイト) "を示します。これは、たとえばUbuntuで採用されているアプローチです: UnitsPolicy-Ubuntu Wiki

注:オプションの使用目的の詳細については、たとえば、 Java-JVMを起動するときのXmsおよびXmxパラメーターは何ですか?

17
nealmcb

簡単な答え:JVMコマンドライン引数で使用されるすべてのメモリサイズは、従来のバイナリ単位で指定されます。キロバイトは1024バイトで、その他は1024の累乗です。

長い答え:

コマンドライン引数に関するこのドキュメントページ は、メモリサイズを受け入れるすべての引数に以下が適用されると述べています。

たとえば、サイズを8 GBに設定するには、引数として8g8192m8388608k、または8589934592のいずれかを指定できます。

-Xmxの場合、次の具体例を示します。

次の例は、さまざまなユニットを使用して、割り当てられたメモリの最大許容サイズを80MBに設定する方法を示しています。

-Xmx83886080
-Xmx81920k
-Xmx80m

ドキュメントを確認する前に(すでに持っていると思いますか?)、HotSpotのソースを確認したところ、メモリ値が src/share/vm/runtime/arguments.cpp で解析されていることがわかりました。 function atomull( "ASCII to memory、unsigned long long"を表すようです):

// Parses a memory size specification string.
static bool atomull(const char *s, julong* result) {
  julong n = 0;
  int args_read = sscanf(s, JULONG_FORMAT, &n);
  if (args_read != 1) {
    return false;
  }
  while (*s != '\0' && isdigit(*s)) {
    s++;
  }
  // 4705540: illegal if more characters are found after the first non-digit
  if (strlen(s) > 1) {
    return false;
  }
  switch (*s) {
    case 'T': case 't':
      *result = n * G * K;
      // Check for overflow.
      if (*result/((julong)G * K) != n) return false;
      return true;
    case 'G': case 'g':
      *result = n * G;
      if (*result/G != n) return false;
      return true;
    case 'M': case 'm':
      *result = n * M;
      if (*result/M != n) return false;
      return true;
    case 'K': case 'k':
      *result = n * K;
      if (*result/K != n) return false;
      return true;
    case '\0':
      *result = n;
      return true;
    default:
      return false;
  }
}

これらの定数KMGは、 src/share/vm/Utilities/globalDefinitions.hpp で定義されています。

const size_t K                  = 1024;
const size_t M                  = K*K;
const size_t G                  = M*K;

テラバイトのTサフィックスのサポートが後で追加されたようであり、まったく文書化されていないことを除いて、これはすべて文書化を確認します。

単位乗数の使用は必須ではないため、10億バイトが必要な場合は、-Xmx1000000000と記述できます。乗数を使用する場合、それらは2進数であるため、-Xmx1Gは2を意味します30 バイト、または1スティックのRAM。

(Javaは、既存の単語を遡及的に再定義しようとするIECの試みよりも前からあるため、これはそれほど驚くべきことではありません。IECが、修飾子が「binary」および「decimal」のメモリユニットで、意味が明確でない場合があります。例:binary gigabytes(GB2)= 10243 バイト、および10進ギガバイト(GB10)= 10003 バイト。しかし、いいえ、彼らは誰もがすでに使用している単語を再定義し、必然的に混乱を爆発させ、これらのピエロの用語「ギビバイト」、「テビバイト」などに固執しました。ああ、神は私たちを惜しまない。)

33
Boann

質問に対する回答を得るには、次の2つのオプションがあります。

a)JDKのソースコードを検査します。申し訳ありませんが、5分でグーグルできませんでした。

b)シミュレーションを作成し、それを数回実行して、いくつかの観察を行います。

public class A {
  public static void main(String[] args) throws Exception {
    System.out.println("total: " + Runtime.getRuntime().totalMemory());
  }
}

そしてそれを数回実行します:

Java -Xms130m -Xmx2G A
total: 131072000
Java -Xms131m -Xmx2G A
total: 132644864
Java -Xms132m -Xmx2G A
total: 132644864
Java -Xms133m -Xmx2G A
total: 134742016
Java -Xms134m -Xmx2G A
total: 134742016

したがって、知識に基づいた推測では、Javaは正確な数値ではなく、要求した数値の2 ^ n近似値を使用します。

5
ya_pulser

別の 質問 _-Xmx_フラグに関しては、Runtime.getRuntime().maxMemory()を使用して現在のサイズを表示します。 _-Xmx1024m_と_-Xmx1g_は同じ出力になり、数値が10ではなく2の累乗であることを示していることにも注意してください。

totalMemory()maxMemory()の違いにも注意してください。
Runtime.getRuntime()。totalMemory()およびfreeMemory()とは何ですか?

1
jaco0646