ما يمكن تعديل SerialVersionUID أثناء تسلسل وتخزينه في جارفيل؟

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

سؤال

أنا مواجهة بعض المشكلات أثناء تسلسل الكائنات (أنا أستخدم JBOSS SHOLOOLS، وتريد تخزين قائمة صفوفا من المعرفة).

عندما أقوم بتسلسل القائمة، قم بتخزين النتيجة في ملف، وتجعله، لا توجد مشكلة، لذلك تعمل بشكل جيد.

ولكن عندما أقوم بتسلسل القائمة، قم بتخزين النتيجة في دفق البايت، ثم احفظه في Jarfile، لا يمكنني ذلك بعد ذلك نجح النتيجة، بسبب هذا الخطأ:

IOException during package import : java.util.ArrayList; local class incompatible: stream classdesc serialVersionUID = 8664875232659988799, local class serialVersionUID = 8683452581122892189

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

أنا بخيبة أمل حقا ولا يمكن أن أذكر حيث قد تكون المشكلة.

ما الذي يمكن تعديل serialversionuid بين فئتين؟ بخلاف نسخة VM أخرى؟


إضافة شفرة المصدر: Exporttojar -> WriterulespackageEndry -> تجديد

/**
 * Writes content provided from a reader into a file contained in a jar.
 * 
 * @param output the output stream to write on
 * @param entryName the name of the file that will contain reader data
 * @param contentReader 
 * 
 * @return the zip entry that has been created into the jar
 */
ZipEntry writeEntry(JarOutputStream output, String entryName, ByteArrayInputStream input) {
    if (output == null || entryName == null || entryName.trim().length() == 0 || input == null) {
        throw new NullPointerException("Null argument passed");
    }

    ZipEntry entry = new ZipEntry(entryName);
    byte[] buffer = new byte[BUFFER_LENGTH];

    try {
        output.putNextEntry(entry);
        int nRead;

        while ((nRead = input.read(buffer, 0, BUFFER_LENGTH)) > 0) {
            output.write(buffer, 0, nRead);
        }

        output.closeEntry();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return entry;
}

/**
 * Export rules files to a serialized object (ArrayList<KnowledgePackage>) into 
 * an output stream, then write the output content as an entry of a jar.
 * 
 * @param os the output jar to write in
 */
void writeRulesPackageEntry(JarOutputStream os) {
    // serialize objects and write them to the output stream
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    RulesPackaging rulesPackaging = new RulesPackaging();
    rulesPackaging.exportResources(this.rules, output);

    // create a new input stream to read written objects from
    ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
    this.writeEntry(os, Product.ENTRY_RULES_PACKAGE, input);
}

/**
 * Creates a JarFile containing resources. 
 * 
 * @param filename the exported jar filename
 * @return the jar as an object, null if an error occured
 */
public JarFile exportToJar(String filename) {
    FileOutputStream fOs;
    JarOutputStream jOs;
    JarFile jar = null;

    try {
        fOs = new FileOutputStream(filename);
        jOs = new JarOutputStream(fOs);

        this.writeRulesPackageEntry(jOs);

        jOs.close();

        // construct a jar from the output jar
        jar = new JarFile(new File(filename));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return jar;
}
هل كانت مفيدة؟

المحلول

ال serialVersionUID لا يتغير. إنها static final تم تعيينه في وقت التجميع (بناء على تجزئة من التعليمات البرمجية المصدر، وأعتقد) ما لم يتم تعيين قيمة صريح في التعليمات البرمجية المصدر.

هناك أكثر قليلا عن ذلك هنا http://mindprod.com/jgloss/serialization.html..

مع الاستثناء الذي تراه الصحيح serialVersionUID بالنسبة ل Java.util.arrieList هو 868345258112289218992899L، والذي تم تعيينه صراحة في التعليمات البرمجية المصدر وظل نفسه لأنه تم تقديم الفصل في 1.2.

كما قلت الخطأ على الأرجح يحدث عند دفق البايت إلى Jarfile - يرجى نشر الرمز الذي تستخدمه للقيام بذلك.

يمكنك نشر رمز المصدر

أظن أن المشكلة تكمن في استخدام java.io.InputStreamReader.

من الجافادوك:

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

بمجرد أن أرى مجموعات الأحرف التي تنطوي على تدفقات غير نصية، أشعر دائما بالمشكوك لأنه من الممكن تعديل الدفق الذي سيتم تعديله أثناء فك التشفير هو سلسلة من البايتات لا يتوافق مع حرف في مجموعة الأحرف (شاهد تلك المربع الصغير الأحرف التي تحدث عند حدوث مشاكل الترميز). سأحاول قراءة البايت مباشرة قبالة java.io.ByteArrayInputStream أنك تغت مع java.io.InputStreamReader في writeRulesPackageEntry(JarOutputStream). وبعد التحويل إلى char[] ليست ضرورية.

نصائح أخرى

مثل النيك تقترح، من المرجح أن تكون المشكلة على الأرجح أنك لا تعامل مع دفق البايتات (التي لم يتم تغييرها أبدا)، ولكن كحرف (التي يمكن أن تكون).

بعد أن قال ذلك، فإن مورد لائق آخر بشأن التسلسل هو فصل مخصص من كتاب كتبته منذ مليون سنة (1997)، "إتقان جافابيين". لحسن الحظ الفصل 11، التسلسل، هو حسب الاقتضاء اليوم كما كان بعد ذلك. قم بتنزيل ملفات PDF المجانية من http://ccd.uab.es/~srobles/manuals/javabeans.

هل هناك أي فرصة أن إصدار سابق تم تسلسله في Jarfile، ومحاولات التسلسل اللاحقة تفشل في الكتابة عليه؟ ثم يمكنك استرجاع البيانات المتسلسلة للإصدار السابق من الفصل، والتي من شأنها أن رمي الخطأ "غير المتوافق".

السبب في أنني أسأل، هو أنني رأيت رسائل خطأ مماثلة باستخدام نظام التخزين المؤقت الخاص بي في الاختيار (EHCACHE) عندما قمت بتحديث فئة متسلسلة، لكن لم أسقط ذاكرة التخزين المؤقت المستمر القديم.

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