Ne neden olabilir java.lang.StackOverflowError
? Aldığım yığın çıktısı hiç çok derin değil (sadece 5 yöntem).
Yanıtlar:
Yöntemler için tekrarlayıcı çağrıları kontrol edin. Esas olarak, bir yöntem için özyinelemeli çağrı olduğunda ortaya çıkar. Basit bir örnek
public static void main(String... args) {
Main main = new Main();
main.testMethod(1);
}
public void testMethod(int i) {
testMethod(i);
System.out.println(i);
}
Burada System.out.println (i); testMethod çağrıldığında art arda yığına itilecektir.
JVM'nin (isteğe bağlı) argümanlarından biri yığın boyutudur. -Xss. Varsayılan değerin ne olduğunu bilmiyorum, ancak yığındaki toplam malzeme miktarı bu değeri aşarsa, bu hatayı alırsınız.
Genel olarak sonsuz özyineleme bunun nedenidir, ancak bunu görüyor olsaydınız, yığın izlemenizde 5'ten fazla kare olurdu.
Bunun gidip gitmediğini görmek için bir -Xss bağımsız değişkeni eklemeyi (veya birinin değerini artırmayı) deneyin.
Aslında java.lang.StackOverflowError hatası neden olan şey genellikle kasıtsız özyinelemedir. Benim için çoğu zaman, gizli yöntem için süper bir yöntem çağırmayı düşündüğüm zamandır. Bu durumda olduğu gibi:
public class Vehicle {
public void accelerate(float acceleration, float maxVelocity) {
// set the acceleration
}
}
public class SpaceShip extends Vehicle {
@Override
public void accelerate(float acceleration, float maxVelocity) {
// update the flux capacitor and call super.accelerate
// oops meant to call super.accelerate(acceleration, maxVelocity);
// but accidentally wrote this instead. A StackOverflow is in our future.
this.accelerate(acceleration, maxVelocity);
}
}
İlk olarak, bir işlevi çağırdığımızda perde arkasında ne olduğunu bilmek yararlıdır. Yöntemin çağrıldığı yerin argümanları ve adresi yığın üzerine itilir (bkz. Http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ), böylece çağrılan yöntem argümanlara erişebilir ve böylece çağrılan yöntem tamamlanır, çalıştırma çağrıdan sonra devam edebilir. Ancak bunu özyinelemeli olarak (ivme, maxVelocity) çağırdığımız için (bir yöntem kendisini çağırdığında özyineleme gevşek bir şekilde gerçekleşir. Daha fazla bilgi için bkz. Http://en.wikipedia.org/wiki/Recursion_(computer_science) ) sonsuz özyineleme olarak bilinen bir durumdayız ve yığınlamaya devam ediyoruz çağrı yığınındaki argümanlar ve dönüş adresi. Çağrı yığını boyut olarak sınırlı olduğundan, sonunda alanımız kalmaz. Çağrı yığınındaki alanın tükenmesi taşma olarak bilinir. Bunun nedeni, sahip olduğumuzdan daha fazla yığın alanı kullanmaya çalışmamız ve verilerin kelimenin tam anlamıyla yığını aşmasıdır. Java programlama dilinde, bu, java.lang.StackOverflow çalışma zamanı istisnasına neden olur ve programı hemen durdurur.
Yukarıdaki örnek biraz basitleştirilmiştir (benim başıma kabul etmek istediğimden daha fazla olmasına rağmen) Aynı şey, izini sürmeyi biraz daha zorlaştıracak şekilde daha kapsamlı bir şekilde gerçekleşebilir. Bununla birlikte, genel olarak, StackOverflow bir kez gerçekleştiğinde çözülmesi oldukça kolaydır.
Teoride, yineleme olmadan bir yığın taşması olması da mümkündür, ancak pratikte bu oldukça nadir bir olay gibi görünebilir.
java.lang.StackOverflowError
Hata java.lang.StackOverflowError
, uygulama yığınının derin özyineleme nedeniyle tükendiğini belirtmek için atılır, yani programınız / betiğiniz çok derin yinelenir.
StackOverflowError
Uzanır VirtualMachineError
JVM olmuştur veya kaynakların tükendi ve can daha da çalışmaz gösterir sınıfı. VirtualMachineError
Uzandığı Error
sınıf bir uygulama yakalamak gerektiğini bu ciddi sorunlara işaret etmek için kullanılır. Bir yöntem kendi throw
cümlesinde bu tür hataları bildirmeyebilir, çünkü bu hatalar asla meydana gelmesi beklenmeyen anormal durumlardır.
Minimal, Complete, and Verifiable Example
:
package demo;
public class StackOverflowErrorExample {
public static void main(String[] args)
{
StackOverflowErrorExample.recursivePrint(1);
}
public static void recursivePrint(int num) {
System.out.println("Number: " + num);
if(num == 0)
return;
else
recursivePrint(++num);
}
}
Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.StackOverflowError
at java.io.FileOutputStream.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
at java.io.BufferedOutputStream.flush(Unknown Source)
at java.io.PrintStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
at java.io.PrintStream.newLine(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11)
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
.
.
.
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
Bir Java Uygulaması tarafından bir işlev çağrısı çağrıldığında , çağrı yığınında bir yığın çerçevesi tahsis edilir . Çağrılan yöntemin, yerel parametreleri ve yöntemin dönüş adresinin parametreleri bulunuyor. Dönüş adresi, başlatılan yöntem döndükten sonra program yürütmesinin devam edeceği yürütme noktasını belirtir. Yeni bir yığın çerçevesi için yer yoksa, Java Sanal Makinesi (JVM) tarafından atılır.stack frame
StackOverflowError
Bir Java uygulamasının yığınını tüketebilecek en yaygın durum özyinelemedir. Özyinelemede, bir yöntem yürütme sırasında kendisini çağırır. Recursion
en güçlü genel amaçlı programlama tekniklerinden biridir, ancak StackOverflowError
kaçınılması için dikkatli kullanılmalıdır .
Bir Java uygulaması tarafından bir işlev çağrısı çağrıldığında, çağrı yığınında bir yığın çerçevesi tahsis edilir. Yığın çerçevesi, çağrılan yöntemin parametrelerini, yerel parametrelerini ve yöntemin dönüş adresini içerir.
Dönüş adresi, başlatılan yöntem döndükten sonra program yürütmesinin devam edeceği yürütme noktasını belirtir. Yeni bir yığın çerçevesi için alan yoksa, StackOverflowError Java Sanal Makinesi (JVM) tarafından atılır .
Bir Java uygulamasının yığınını tüketebilecek en yaygın durum özyinelemedir.
Lütfen bir göz at
Verileri ayrıştırırken Hazırda Bekletme kullanıcıları için çözüm:
Bu hatayı aldım çünkü her iki tarafa eşlenmiş nesnelerin bir listesini ayrıştırıyordum @OneToMany
ve@ManyToOne
sonsuz bir döngüye neden olan jackson kullanarak json'u .
Eğer aynı durumda iseniz kullanarak bu çözebilir @JsonManagedReference
ve@JsonBackReference
notları .
API'den Tanımlar:
JsonManagedReference ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html ):
Ek açıklamalı özelliğin alanlar arasındaki iki yönlü bağlantının parçası olduğunu belirtmek için kullanılan ek açıklama; ve rolünün "ana" (veya "ileri") bağlantı olduğunu. Özelliğin değer türü (sınıfı), JsonBackReference ile açıklanmış tek bir uyumlu özelliğe sahip olmalıdır. Bağlantı, bu açıklama ile açıklanmış özellik normal olarak işlenecek şekilde işlenir (normal olarak serileştirilir, seriyi kaldırma için özel bir işlem yoktur); özel işlem gerektiren, eşleşen geri referanstır
JsonBackReference: ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html ):
İlişkili özelliğin alanlar arasındaki iki yönlü bağlantının parçası olduğunu belirtmek için kullanılan ek açıklama; ve rolü "alt" (veya "geri") bağlantıdır. Özelliğin değer türü bir çekirdek olmalıdır: Koleksiyon, Harita, Dizi veya numaralandırma olamaz. Bağlantı, bu ek açıklama ile açıklama eklenen özellik serileştirilmeyecek şekilde işlenir; ve seriyi kaldırma sırasında, değeri "yönetilen" (ileri) bağlantıya sahip olan örneğe ayarlanır.
Misal:
Owner.java:
@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;
Car.java:
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
Başka bir çözüm, @JsonIgnore
sadece alana null atan kullanmaktır.
Her ikisi de veri üyeleri olarak birbirinin nesnesiyle iki POJO sınıfı oluşturduğum hazırda bekletme ile bir program oluşturdum. Ana yöntemde onları veritabanına kaydetmeye çalıştığımda da bu hatayı aldım.
Bunun nedeni, her iki sınıfın da birbirine başvurması, dolayısıyla bu hataya neden olan bir döngü oluşturmasıdır.
Bu nedenle, programınızda bu tür bir ilişki olup olmadığını kontrol edin.
Yığın Taşması istisnaları, bir iş parçacığı yığınının boyutu maksimum sınıra ulaşana kadar büyümeye devam ettiğinde ortaya çıkabilir.
Yığın Boyutları (Xss ve Xmso) seçeneklerini ayarlama ...
Bu bağlantıyı görmenizi öneririm: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Bağlantıda görebileceğiniz gibi, StackOverflowError için birçok olası neden vardır ....
Benim durumumda iki faaliyetim var. İkinci aktivitede onCreate yöntemine süper koymayı unuttum.
super.onCreate(savedInstanceState);
StackOverflowError
, soruyu yanıtladığını sanmıyorum. Bence uygun bir cevap, bu istisnayı elde etmenin çok fazla özyineleme kullanmaktan başka yollarını listelemeli veya böyle bir istisnayı elde etmenin kesinlikle başka bir yolu olmadığını, elle atmaktan başka bir yol olmadığını söylemelidir.