Имеет ли java -Xmx1G 10 ^ 9 или 2 ^ 30 байт?

И вообще, это единицы, используемые для опций -Xmx, -Xms и -Xmn ( "k", "M" и "G" или менее стандартных возможностей "K", "m", или "g" ) Двоичный префикс (например, мощности 1024) или значения 1000?

В руководствах говорится, что они представляют килобайты (кБ), мегабайты (МБ) и гигабайты (ГБ), предполагая, что они обладают мощностью 1000, как определено в оригинальной SI. Мои неофициальные тесты (которые я не очень уверен) предполагают, что они действительно kibibytes (kiB), mebibytes (MiB) и gibibytes (GiB), все полномочия 1024.

Итак, что верно? Например. какой Java-код будет показывать текущий размер?

Использование кратных 1024 не удивительно для размеров ОЗУ, поскольку оперативная память обычно физически выкладывается путем удвоения аппаратных модулей. Но использование единиц четким и стандартным образом становится все более важным, поскольку мы достигаем больших и больших полномочий, поскольку потенциал для путаницы растет. Единица "t" также принимается моей JVM, а 1 TiB на 10% больше, чем 1 ТБ.

Примечание: если они действительно являются двоичными кратными, я предлагаю обновить документацию и пользовательские интерфейсы, чтобы быть очень ясными об этом, с примерами типа " Добавить букву k или K, чтобы указать кибиты (1024 байта) или m или M, чтобы указать mebibytes (1048576 bytes). Это подход, принятый, например, в Ubuntu: UnitsPolicy - Ubuntu Wiki.

Примечание: для получения дополнительной информации о том, какие параметры используются, см., например, java - Каковы параметры Xms и Xmx при запуске JVM?.

Ответ 1

Короткий ответ: все размеры памяти, используемые аргументами командной строки JVM, указаны в традиционных двоичных единицах, где килобайт равен 1024 байтам, а остальные - мощности 1024.

Длинный ответ:

Эта страница документации в аргументах командной строки говорит, что для всех аргументов, принимающих размеры памяти, применяется следующее:

Например, чтобы установить размер до 8 ГБ, в качестве аргумента можно указать либо 8g, 8192m, 8388608k, либо 8589934592.

Для -Xmx он дает следующие конкретные примеры:

В следующих примерах показано, как установить максимальный разрешенный размер выделенной памяти на 80 МБ с использованием различных единиц:

-Xmx83886080
-Xmx81920k
-Xmx80m

Прежде чем я подумал проверить документацию (предположил, что у вас уже есть?), я проверил источник HotSpot и обнаружил, что значения памяти анализируются в src/share/vm/runtime/arguments.cpp с помощью функции atomull (которая, как представляется, означает "ASCII в память, без знака длинный" ):

// 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;
  }
}

Эти константы K, M, G определены в src/share/vm/utilities/globalDefinitions.hpp:

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

Все это подтверждает документацию, за исключением того, что поддержка суффикса T для терабайт, по-видимому, была добавлена ​​позже и вообще не документирована.

Не обязательно использовать единичный множитель, поэтому, если вы хотите один миллиард байт, вы можете написать -Xmx1000000000. Если вы используете множитель, они двоичные, поэтому -Xmx1G означает 2 30 байт или одну палку o 'RAM.

(что не удивительно, потому что Java предшествует попытке IEC ретроактивно переопределять существующие слова. Путаница могла быть сохранена, если бы МЭК просто советовал устранить неоднозначность блоков памяти с помощью "двоичных" и "десятичных" классификаторов, например, двоичные гигабайты (GB 2) = 1024 3 а десятичные гигабайты (GB 10) = 1000 3. Но нет, они переопределили слова, которые все уже использовали, неизбежно взорвали путаницу и оставили нас застрявшими с этими клоунскими терминами "гиббите", "тебибите" и остальным. запасьте нас.)

Ответ 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 аппроксимацию запрашиваемого вами номера.

Ответ 3

В другом question относительно флага -Xmx Runtime.getRuntime().maxMemory() используется для отображения текущего размера. Также отмечается, что -Xmx1024m и -Xmx1g приводят к идентичному выходу, что указывает на то, что числа имеют значения двух, а не десяти.

Обратите внимание на разницу между totalMemory() и maxMemory().
Что такое Runtime.getRuntime(). totalMemory() и freeMemory()?