لماذا يتجاوز هذا الحد 65،535 البايت في منشئين Java والتهفية الثابتة؟

StackOverflow https://stackoverflow.com/questions/788787

  •  16-09-2019
  •  | 
  •  

سؤال

إخلاء المسئولية: أدرك أنني أستطيع توليد هذا في وقت التشغيل في جافا، وكان هناك حاجة إلى حالة خاصة للغاية أثناء اختبار الأداء بعض التعليمات البرمجية. لقد وجدت نهجا مختلفا، لذلك الآن هذا مجرد فضول أكثر من أي شيء عملي.

لقد جربت ما يلي كحقل ثابت، كحقل مثيل، وتهيئة مباشرة داخل المنشئ. في كل مرة تقوم فيها الكسوف بإبلاغني بأن "رمز البناء TestData () يتجاوز حدود البايتات 65535" أو "رمز التهيئة الثابت يتجاوز حد البايت 65535".

هناك 10000 صحيحة. إذا كانت كل int هي 4 بايت (32 مليار)، فهل لن يكون 40،000 بايت؟ هل هناك حقا أكثر من 25،0000 بايت من النفقات العامة بالإضافة إلى البيانات فقط بناء صفيف؟

يتم إنشاء البيانات مع هذا القليل صغير من الثعبان:

#!/usr/bin/python

import random;
print "public final int[] RANDOM_INTEGERS = new int[] {";
for i in range(1,10000):
    print str(int(random.uniform(0,0x7fffffff))) + ",";
print "};";

إليك عينة صغيرة:

public final int[] RANDOM_INTEGERS = new int[] {
    963056418, 460816633, 1426956928, 1836901854, 334443802, 721185237, 488810483,
    1734703787, 1858674527, 112552804, 1467830977, 1533524842, 1140643114, 1452361499,
    716999590, 652029167, 1448309605, 1111915190, 1032718128, 1194366355, 112834025,
    419247979, 944166634, 205228045, 1920916263, 1102820742, 1504720637, 757008315,
    67604636, 1686232265, 597601176, 1090143513, 205960256, 1611222388, 1997832237,
    1429883982, 1693885243, 1987916675, 159802771, 1092244159, 1224816153, 1675311441,
    1873372604, 1787757434, 1347615328, 1868311855, 1401477617, 508641277, 1352501377,
    1442984254, 1468392589, 1059757519, 1898445041, 1368044543, 513517087, 99625132,
    1291863875, 654253390, 169170318, 2117466849, 1711924068, 564675178, 208741732,
    1095240821, 1993892374, 87422510, 1651783681, 1536657700, 1039420228, 674134447,
    1083424612, 2137469237, 1294104182, 964677542, 1506442822, 1521039575, 64073383,
    929517073, 206993014, 466196357, 1139633501, 1692533218, 1934476545, 2066226407,
    550646675, 624977767, 1494512072, 1230119126, 1956454185, 1321128794, 2099617717,
    //.... to 10,0000 instances
هل كانت مفيدة؟

المحلول

هنا هو bytecode لتهيئة صفيف مع {1000001، 1000002، 1000003}:

 5  iconst_3
 6  newarray int [10]
 8  dup
 9  iconst_0
10  ldc <Integer 1000001> [12]
12  iastore
13  dup
14  iconst_1
15  ldc <Integer 1000002> [13]
17  iastore
18  dup
19  iconst_2
20  ldc <Integer 1000003> [14]
22  iastore
23  putfield net.jstuber.test.TestArrayInitializingConstructor.data : int[] [15]

لذلك بالنسبة إلى هذه الصفيف الصغيرة يتطلب كل عنصر 5 بايت من جافا bytecode. بالنسبة لمجموعك الأكبر، سيستخدم مؤشر الصفيف والفهرس في المسبح الثابت 3 بايت لمعظم العناصر، مما يؤدي إلى 8 بايت لكل عنصر صفيف. لذلك بالنسبة إلى 10000 عنصر يتعين عليك توقعه حوالي 80 كيلو بايت من الكود البايت.

يبدو رمز تهيئة صفائف كبيرة مع مؤشرات 16 بت مثل هذا:

2016  dup
2017  sipush 298
2020  ldc_w <Integer 100298> [310]
2023  iastore
2024  dup
2025  sipush 299
2028  ldc_w <Integer 100299> [311]

نصائح أخرى

يتم ترجمة حرف مجموعة الصفيف إلى رمز البايت الذي يملأ الصفيف مع القيم، لذلك تحتاج إلى عدد قليل من بايت لكل رقم.

لماذا لا تنقل تلك البيانات إلى مورد تقوم بتحميله في وقت تحميل الفصل في كتلة تهيئة ثابتة؟ يمكن بسهولة القيام بذلك باستخدام MyClass.class.getClassLoader().getResourceAsStream(). وبعد يبدو أن هذا هو المكان الذي ينتمي إليه، على أي حال.

أو الأفضل من ذلك، إنشاء القيم العشوائية في كتلة التهيئة الثابتة باستخدام أدوات Java المتاحة. وإذا كنت بحاجة إلى أرقام "عشوائية" قابلة للتكرار، ثم فقط البذور Random مثيل رقم ثابت ولكنه اختيار عشوائيا في كل مرة.

إلى جانب قيم الأعداد الصحيحة، يحتاج المنشئ والتهيئة إلى احتواء تعليمات JVM لتحميل الأعداد الصحيحة في الصفيف.

تتمثل النهج الأكثر بساطة وأكثر عملية في تخزين الأرقام في ملف، إما بتنسيق ثنائي أو كنص.

لا أعرف ما تهما به Java صفائف بهذه الطريقة، لكنها لا تهيئة صففا كبيرة بكفاءة.

أعتقد أن حجم التعليمات البرمجية في الشخصيات هو أكثر من 65535. وليس الذاكرة التي تم التقاطها بواسطة 10000 أعداد صحيحة.

أعتقد أنه من الممكن أن يكون هذا مقدار الذاكرة المطلوبة لتمثيل تلك الأبدية الأبجدية الأبجدية. أعتقد أن هذا الحد قد ينطبق على الكود نفسه، لذلك، كل int، على سبيل المثال: 1494512072 يأخذ فعلا 10 بايت (واحد لكل رقم) بدلا من 4 بايت فقط المستخدمة في INT32.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top