تقوم مهام <javac> الخاصة بـ Ant بطرح StackOverflowException

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

  •  08-06-2019
  •  | 
  •  

سؤال

أحاول تجميع أكثر من 100 فئة جافا من حزم مختلفة من دليل نظيف (بدون تجميعات تدريجية) باستخدام مهام النمل التالية:

<target name="-main-src-depend">
    <depend srcdir="${src.dir}" 
            destdir="${bin.dir}" 
            cache="${cache.dir}"
            closure="true"/>
</target>   

<target name="compile" depends="-main-src-depend"
        description="Compiles the project.">

    <echo>Compiling</echo>

    <javac  target="${javac.target}"
            source="${javac.source}"
            debug="${javac.debug}"
            srcdir="${src.dir}"
            destdir="${bin.dir}">
        <classpath>
            <path refid="runtime.classpath"/>
            <path refid="compile.classpath"/>
        </classpath>
    </javac>
</target>

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

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

هل كانت مفيدة؟

المحلول

سيكون من الجميل أن نعرف.ما الذي يمكن أن يسبب أو يسبب stackoverflowerror أثناء تجميع رمز Java؟

من المحتمل أن تقييم التعبير الطويل في ملف جافا الخاص بك يستهلك الكثير من الذاكرة ولأن ذلك يتم بالتزامن مع تجميع الفئات الأخرى، فإن الجهاز الظاهري ينفد من مساحة المكدس.ربما تكون فئتك التي تم إنشاؤها تدفع الحدود القانونية لمحتوياتها.انظر الفصل 4.10 قيود جهاز Java الظاهري في مواصفات الجهاز الظاهري جافا، الإصدار الثاني.

الإصلاح 1:إعادة بناء الفصل

نظرًا لأنه يتم إنشاء فصلك الدراسي، فقد لا يكون هذا خيارًا.ومع ذلك، من المفيد النظر في الخيارات التي توفرها أداة إنشاء الفصل لديك لمعرفة ما إذا كان بإمكانها إنتاج شيء أقل إزعاجًا.

الإصلاح 2:زيادة حجم المكدس

أظن كيرون لديه حل واحد عندما يذكر الوسيطة -Xss. javac يأخذ عددًا من الوسائط غير القياسية التي ستختلف بين الإصدارات وبائعي المترجمات.

المترجم الخاص بي:

$ javac -version
javac 1.6.0_05

لسرد كافة الخيارات لذلك، سأستخدم هذه الأوامر:

javac -help
javac -X
javac -J-X

أنا يفكر الحد الأقصى للمكدس لـ javac هو 512 كيلو بايت بشكل افتراضي.يمكنك زيادة حجم المكدس لهذا المترجم إلى 10 ميجابايت باستخدام هذا الأمر:

javac -J-Xss10M Foo.java

قد تتمكن من تمرير هذا في ملف Ant بامتداد com.compilarg عنصر متداخل في ملفك javac مهمة.

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J-Xss10M" />
</javac>

نصائح أخرى

  <javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
      <compilerarg value="-J-Xss10M" />
    </javac>

من التعليق أعلاه غير صحيح.أنت بحاجة إلى مسافة بين -J و -X، كما يلي:

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J -Xss10M" />
</javac>

لتجنب الخطأ التالي:

 [javac] 
[javac] The ' characters around the executable and arguments are
[javac] not part of the command.
[javac] Files to be compiled:

...[جافاك] جافاك:علامة غير صالحة:-J-XSS1M [Javac] الاستخدام:javac

حاول إضافة بعض الاختلافات في هذه السمات إلى ملف نملة javac مهمة خط:

memoryinitialsize="256M" memorymaximumsize="1024M"

يمكنك أيضًا المحاولة fork="true", ، لست متأكدًا مما إذا كان هذا يسمح لك بتعيين قيم للمكدس والكومة (المعروف أيضًا باسم -Xm1024)، ولكنه قد يساعد (إذا كان سيعمل من سطر الأوامر، ولكن ليس في Ant).

[يحرر]:تمت إضافة الرابط - javac مهمة يبدو أن الصفحة تشير إلى أن المعلمات أعلاه تتطلب أن تقوم بتعيينها أيضًا fork="true".

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

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

أحد الحلول الممكنة هو ببساطة زيادة حجم المكدس باستخدام -Xss حجة إلى JVM؛إما لتشغيل JVM ant أو عن طريق الإعداد fork="true" و أ <compilerarg> على ال <javac> مهمة.في الواقع، الآن بعد أن أفكر في الأمر، هل تختفي المشكلة بمجرد إدخالها fork="true"?

وهنا ما وجدته.بعد نشر سؤالي تابعت وعدلت مهمة الترجمة بالسمات fork="true", memoryinitialsize="256m" و memorymaximumsize="1024m" (وجدت اليوم أن هذا تم اقتراحه بواسطة Kieron وjmanning2k، شكرًا على وقتك).هذا لم يحل المشكلة رغم ذلك.

قررت أن أبدأ في إزالة الفئات من الشجرة المصدر لمعرفة ما إذا كان بإمكاني تحديد المشكلة.تبين أن لدينا فئة عميل خدمة الويب لـ المحور 1.4 الذي تم إنشاؤه تلقائيًا من ملف WSDL.الآن، هذه الفئة عبارة عن وحش (كما هو الحال في Frankenstein)، فهي تحتوي على 167 عضوًا ميدانيًا (جميعهم من النوع String)، و167 زوجًا من getter/setter (واحد لكل حقل)، ومنشئ يستقبل جميع الحقول الـ 167 كمعلمات، و يساوي الطريقة التي تقارن جميع الحقول الـ 167 بطريقة غريبة.تتم المقارنة لكل حقل على النحو التالي:

(this.A == null && other.getA() == null) || (this.A != null && this.A.equals(other.getA()))

نتيجة هذه المقارنة هي "anded" (&&) مع نتيجة مقارنة الحقل التالي، وهكذا.يستمر الفصل باستخدام أسلوب hashCode الذي يستخدم أيضًا جميع الحقول وبعض أساليب تسلسل XML المخصصة وأسلوبًا يُرجع كائن بيانات التعريف الخاص بالمحور الذي يصف الفئة ويستخدم أيضًا جميع أعضاء الحقل.

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

أعلم الآن أن إزالة هذا الملف المصدر الفردي قد حل المشكلة.ومع ذلك، ليس لدي أي فكرة على الإطلاق عن سبب تسبب هذه الفئة بالذات في المشكلة.سيكون من الجميل أن نعرف.ما الذي يمكن أن يسبب أو يسبب StackOverflowError أثناء تجميع كود Java؟أعتقد أنني سأنشر هذا السؤال.

للمهتمين:

  • ويندوز إكس بي SP2
  • صن JDK 1.4.2_17
  • النملة 1.7.0
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top