Jenkins CI - Tidak dapat mengalokasikan memori

9

Saya menguji jenkins-ci dengan sukses di ubuntu 10.4 (dengan vmware fusion) di komputer lokal saya. Sekarang saya ingin menginstal dan menggunakannya di server virtual saya di hosteurope. Instalasi dasar tidak masalah, tapi sekarang saya punya masalah dengan proyek build saya.

Setelah menarik pembaruan lincah dari repositori, semut dipanggil dan melempar kesalahan berikut dalam proyek build saya:

"Buildfile: /var/lib/jenkins/workspace/concrete5-seed-clean/build.xml [properti] java.io.IOException: Tidak dapat menjalankan program" / usr / bin / env ": java.io.IOException: error = 12, Tidak dapat mengalokasikan memori "

Ada masalah yang diketahui dengan ukuran tumpukan di server virtual di hosteurope ( http://faq.hosteurope.de/index.php?cpid=13918 ), jadi saya mencoba mengatur ukuran tumpukan secara manual:

# for ant
export ANT_OPTS="-Xms512m -Xmx512m"

# jenkins
# edited /etc/default/jenkins, added line 
JAVA_ARGS="-Xms512m -Xmx512m"
# restarted jenkins via /etc/init.d/jenkins restart 

Setelah mengatur ini untuk semut, perintah "ant -diagnostics" dijalankan dan tidak menyebabkan kesalahan, tetapi kesalahan masih terjadi ketika saya mencoba membangun proyek.

Rincian Server: - http://www.hosteurope.de/produkt/Virtual-Server-Linux-L

  • Ubuntu 10.4 LTS
  • RAM: 1GB / Dinamis 2GB

Pertanyaan saya: - Apakah 1GB cukup untuk Jenkins atau apakah saya harus memutakhirkan server? - Apakah kesalahan ini disebabkan oleh semut atau jenkins?

Pembaruan: Saya menjalankannya dengan opsi semut -Xmx128m -Xms128m, tetapi kadang-kadang kesalahan terjadi lagi. (Ini membuatku takut, karena aku tidak bisa mereproduksinya sekarang: /)

Bantuan sangat dihargai!

Cheers, Matthias

Programmieraffe
sumber
Saya memecahkan masalah ini dengan menetapkan file konfigurasi jenkins: JENKINS_JAVA_OPTIONS = "- Djava.awt.headless = true -Xms500m -Xmx1000m"
herbertD

Jawaban:

10

Orien benar, ini adalah fork () system call yang dipicu oleh ProcessBuilder atau Runtime.exec atau cara lain dari JVM yang menjalankan proses eksternal (mis. JVM lain yang menjalankan semut, perintah git, dll.).

Ada beberapa posting di milis Jenkins tentang ini: Tidak dapat menjalankan program "git" ... error = 12, Tidak dapat mengalokasikan memori

Ada deskripsi yang bagus tentang masalah pada daftar dev SCons: fork () + exec () vs posix_spawn ()

Ada laporan bug JVM lama dengan solusi: Gunakan posix_spawn, bukan fork, pada S10 untuk menghindari pertukaran swap . Tapi saya tidak yakin apakah ini benar-benar berhasil masuk ke JDK7 karena komentarnya adalah rencananya.

Singkatnya, pada sistem mirip Unix, ketika satu proses (misalnya JVM) perlu meluncurkan proses lain (misalnya git) panggilan sistem dibuat fork()yang secara efektif menduplikasi proses saat ini dan semua memorinya (Linux dan yang lainnya mengoptimalkan ini dengan salinan -on-tulis sehingga memori tidak benar-benar disalin sampai anak mencoba menulis ke sana). Proses duplikat kemudian membuat panggilan sistem lain, exec()untuk meluncurkan proses lain (misalnya git) di mana semua memori yang disalin dari proses induk dapat dibuang oleh sistem operasi. Jika proses induk menggunakan memori dalam jumlah besar (seperti proses JVM cenderung lakukan), panggilan untuk fork()dapat gagal jika sistem operasi menentukan tidak memiliki cukup memori + swap untuk menampung dua salinan, bahkan jika proses anak tidak akan pernah benar-benar gunakan memori yang disalin.

Ada beberapa solusi:

  • Tambahkan lebih banyak memori fisik / RAM ke mesin.

  • Tambahkan lebih banyak ruang swap untuk mengelabui fork()bekerja, meskipun ruang swap tidak sepenuhnya diperlukan untuk apa pun. Ini adalah solusi yang saya pilih karena cukup mudah untuk menambahkan swapfile, dan saya tidak ingin hidup dengan potensi proses yang terbunuh karena terlalu banyak berkomitmen.

  • Di Linux, aktifkan overcommit_memoryopsi sistem vm ( / proc / sys / vm / overcommit_memory ). Dengan overcommit, panggilan untuk fork()selalu berhasil, dan karena proses anak sebenarnya tidak akan menggunakan salinan memori itu, semuanya baik-baik saja. Tentu saja, mungkin saja dengan overcommit, proses Anda akan benar-benar mencoba menggunakan lebih banyak memori daripada yang tersedia dan akan dibunuh oleh kernel. Apakah ini sesuai tergantung pada penggunaan lain dari mesin. Mesin misi kritis mungkin tidak boleh mengambil risiko pembunuh kehabisan memori menjalankan amuk. Tetapi server pengembangan internal yang mampu menghentikan beberapa waktu akan menjadi tempat yang baik untuk mengaktifkan overcommit.

  • Ubah JVM untuk tidak menggunakan fork()+ exec()tetapi untuk menggunakan posix_spawn()bila tersedia. Ini adalah solusi yang diminta dalam laporan bug JVM di atas dan disebutkan pada milis SCons. Ini juga diterapkan di java_posix_spawn .

    Saya mencoba mencari tahu apakah perbaikan itu berhasil masuk ke JDK7. Jika tidak, saya ingin tahu apakah orang-orang Jenkins akan tertarik pada pekerjaan di sekitar seperti java_posix_spawn. Tampaknya ada upaya untuk mengintegrasikannya ke dalam Apache commons-exec .

    Programmieraffe, saya tidak 100% yakin, tetapi tautan Anda menyarankan perbaikan di JDK7 dan JDK6 1.6.0_23 dan yang lebih baru. Sebagai catatan, saya menjalankan OpenJDK 1.6.0_18.

Lihat /programming/1124771/how-to-solve-java-io-ioexception-error-12-cannot-allocate-memory-calling-run

Patrick
sumber
Terima kasih atas jawaban yang sudah dihapus! Dalam posting terkait Alf Høgemark mengatakan bahwa ini sudah diperbaiki sekarang: ( stackoverflow.com/a/9127548/809939 ) Dapatkah seseorang mengkonfirmasi ini? Saya akan mencoba memperbarui versi java saya juga.
Programmieraffe
Pertanyaan tambahan: Apa yang akan Anda usulkan? Overcommit-Memory-Setting? Salam, Matthias
Programmieraffe
1
Menambahkan swapfile mudah dan mudah. Untuk Ubuntu 12.04 (walaupun itu harus berlaku sebagian besar untuk Linux pada umumnya), artikel ini sangat sederhana: digitalocean.com/community/articles/…
davemyron
1

Perhatikan pesan pengecualian: Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory"Proses Java mencoba untuk memotong proses baru untuk menjalankan perintah /usr/bin/envtetapi sistem operasi telah kehabisan sumber daya memori untuk membuat proses baru. Ini tidak sama dengan Java VM kehabisan memori sehingga tidak ada jumlah mengutak-atik -Xmx akan memperbaikinya. Anda harus memonitor sumber daya memori Anda saat menjalankan build Anda. Meningkatkan ruang swap kemungkinan akan memperbaiki masalah Anda.

orien
sumber
Ini adalah mesin Java Virtual (salah satu tumpukan, atau tumpukan) yang kehabisan memori BUKAN sistem komputer host.
mdpc
Maafkan singkatnya jawaban asli saya. Saya telah memperbaruinya untuk menjelaskan mengapa JVM tidak kehabisan memori.
orien
0

Kemungkinan ANT_OPTS diganti oleh Jenkins. Anda juga dapat mengatur opsi langsung di file build Anda sehingga Anda dapat mengontrol alokasi memori secara independen dari lingkungan (shell, Jenkins, ...). Dalam file build Anda (contoh:

<java fork="true" classname="..." >
    <jvmarg line="-Xms512M -Xmx512M" />
Matteo
sumber