อะไรทำให้ java.lang.IncompatibleClassChangeError?


218

ฉันบรรจุไลบรารี Java เป็น JAR และมันกำลังขว้างหลายjava.lang.IncompatibleClassChangeErrorครั้งเมื่อฉันพยายามเรียกใช้เมธอดจากมัน ข้อผิดพลาดเหล่านี้ดูเหมือนจะสุ่ม ปัญหาประเภทใดที่ทำให้เกิดข้อผิดพลาดนี้


ในโครงการ Eclipse ที่ฉันกำลังทดสอบ Apache FOP 1.0 และ Barcode4J ดูเหมือนว่าไลบรารีเพิ่มเติมที่มาพร้อมกับ Barcode4J จะเอาชนะคนที่มาพร้อมกับ FOP (บางรุ่นมีหมายเลขรุ่นที่สูงกว่า) เป็นกรณีที่ต้องระวังอย่างมากในสิ่งที่คุณใส่ในเส้นทางการสร้าง / classpath ของคุณ
Wivani

คำตอบ:


170

ซึ่งหมายความว่าคุณได้ทำการเปลี่ยนแปลงไบนารีที่เข้ากันไม่ได้กับไลบรารีโดยไม่ต้องคอมไพล์รหัสไคลเอนต์ใหม่ ข้อกำหนดภาษา Java §13ให้รายละเอียดการเปลี่ยนแปลงทั้งหมดอย่างเด่นชัดที่สุดเปลี่ยนstaticเขตข้อมูล / วิธีการที่ไม่ใช่ภาคเอกชนให้เป็นstaticหรือในทางกลับกัน

คอมไพล์รหัสไคลเอนต์กับไลบรารีใหม่และคุณควรจะไป

อัปเดต: หากคุณเผยแพร่ไลบรารีสาธารณะคุณควรหลีกเลี่ยงการเปลี่ยนแปลงไบนารีที่เข้ากันไม่ได้มากที่สุดเท่าที่จะทำได้เพื่อรักษาสิ่งที่รู้จักกันในชื่อ "ความเข้ากันได้ของไบนารีย้อนหลัง" การอัพเดตไหการพึ่งพาเพียงอย่างเดียวไม่ควรทำให้แอพพลิเคชั่นหรือบิลด์เสียหาย หากคุณจำเป็นต้องหยุดการทำงานร่วมกันของไบนารีแบบย้อนกลับขอแนะนำให้เพิ่มหมายเลขเวอร์ชันหลัก (เช่นจาก 1.xy เป็น 2.0.0) ก่อนปล่อยการเปลี่ยนแปลง


2
ด้วยเหตุผลบางประการนักพัฒนาซอฟต์แวร์ที่นี่กำลังมีปัญหาซึ่งการคอมไพล์รหัสลูกค้าซ้ำอีกครั้งไม่สามารถแก้ไขปัญหาได้อย่างแน่นอน ด้วยเหตุผลบางอย่างถ้าพวกเขาแก้ไขไฟล์ที่มันเกิดขึ้นและคอมไพล์ข้อผิดพลาดจะไม่เกิดขึ้นที่นั่นอีก แต่จะสุ่มป๊อปอัพที่อื่นในโครงการที่มีการอ้างอิงไลบรารี ฉันอยากรู้ว่าสิ่งใดที่อาจทำให้เกิดสิ่งนี้ได้
Zombies

5
คุณได้ลองทำการ build แบบใหม่ (ลบ*.classไฟล์ทั้งหมด) แล้วทำการคอมไพล์ใหม่หรือไม่? การแก้ไขไฟล์มีผลคล้ายกัน
notnoop

ไม่มีรหัสที่สร้างขึ้นแบบไดนามิก .... เว้นแต่คุณจะถือว่า JSP เป็นเช่นนั้น เราลองลบไฟล์คลาสและดูเหมือนว่ามันจะไม่ช่วย สิ่งที่แปลกคือมันไม่ได้เกิดขึ้นกับฉัน แต่มันเกิดขึ้นกับนักพัฒนาคนอื่น ๆ
Zombies

2
คุณสามารถมั่นใจได้หรือไม่ว่าเมื่อคุณสร้าง clean clean คุณกำลังคอมไพล์กับ jars เดียวกันกับที่คุณรันด้วยหรือไม่?
notnoop

มีบางสิ่งที่เกี่ยวข้องกับแพลตฟอร์ม 32 บิตหรือ 64 บิตฉันพบข้อผิดพลาดเฉพาะในแพลตฟอร์ม 64 บิตเท่านั้น
cowboi-peng

96

ไลบรารีที่จัดทำใหม่ของคุณไม่รองรับไบนารีย้อนหลัง (BC) กับเวอร์ชันเก่า ด้วยเหตุนี้ไคลเอนต์ไลบรารีที่ไม่ได้คอมไพล์ใหม่อาจมีข้อยกเว้น

นี่คือรายการการเปลี่ยนแปลงที่สมบูรณ์ใน Java Library API ที่อาจทำให้ไคลเอนต์ที่สร้างด้วยไลบรารี่เวอร์ชั่นเก่าโยน java.lang IncompatibleClassChangeErrorหากพวกเขาทำงานบนใหม่ (เช่นทำลาย BC):

  1. เขตข้อมูลที่ไม่ใช่ครั้งสุดท้ายกลายเป็นแบบคงที่
  2. เขตข้อมูลไม่คงที่กลายเป็นไม่คงที่
  3. คลาสกลายเป็นอินเตอร์เฟส
  4. อินเตอร์เฟสกลายเป็นคลาส
  5. ถ้าคุณเพิ่มฟิลด์ใหม่ในคลาส / อินเทอร์เฟซ (หรือเพิ่มซูเปอร์คลาส / อินเทอร์เฟซใหม่) จากนั้นสแตติกฟิลด์จากซูเปอร์อินเทอร์เฟซของคลาสลูกค้า C อาจซ่อนฟิลด์เพิ่ม (ด้วยชื่อเดียวกัน) ที่สืบทอดจาก ซุปเปอร์คลาสของ C (กรณีที่หายากมาก)

หมายเหตุ : มีจำนวนมากมีข้อยกเว้นอื่น ๆ : เกิดจากการเปลี่ยนแปลงอื่น ๆ ที่เข้ากันไม่NoSuchFieldError , NoSuchMethodError , IllegalAccessError , InstantiationError , VerifyError , NoClassDefFoundErrorและAbstractMethodError

บทความที่ดีกว่าเกี่ยวกับ BC คือ"การพัฒนา API ที่ใช้ Java 2: การบรรลุความเข้ากันได้ของ API แบบไบนารี" ที่เขียนโดย Jim des Rivières

นอกจากนี้ยังมีเครื่องมืออัตโนมัติเพื่อตรวจจับการเปลี่ยนแปลงดังกล่าว:

การใช้ japi-Compliance-checker สำหรับห้องสมุดของคุณ:

japi-compliance-checker OLD.jar NEW.jar

การใช้เครื่องมือ clirr:

java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar

โชคดี!


59

แม้ว่าคำตอบเหล่านี้จะถูกต้องทั้งหมดการแก้ไขปัญหามักจะยากขึ้น โดยทั่วไปแล้วเป็นผลมาจากสองรุ่นที่แตกต่างกันเล็กน้อยของการพึ่งพากันใน classpath และมักจะเกิดจากซูเปอร์คลาสที่แตกต่างกันกว่าเดิมที่รวบรวมมาจากการอยู่ใน classpath หรือการนำเข้าของการปิด transitive บางอย่างที่แตกต่างกัน การสร้างอินสแตนซ์และการเรียกใช้คอนสตรัคเตอร์ (หลังจากการโหลดคลาสที่ประสบความสำเร็จและการเรียกใช้ ctor คุณจะได้รับNoSuchMethodExceptionหรืออะไรก็ตาม)

หากพฤติกรรมปรากฏขึ้นแบบสุ่มเป็นไปได้ว่าผลลัพธ์ของโปรแกรมมัลติเธรดที่โหลดขึ้นต่อกันต่างกันของสกรรมกริยาตามรหัสที่ได้รับผลกระทบก่อน

ในการแก้ไขปัญหาเหล่านี้ให้ลองเรียกใช้ VM ด้วย-verboseอาร์กิวเมนต์เพื่อดูคลาสที่โหลดเมื่อมีข้อยกเว้นเกิดขึ้น คุณควรเห็นข้อมูลที่น่าแปลกใจ ตัวอย่างเช่นการมีการอ้างอิงและรุ่นเดียวกันหลายชุดที่คุณไม่เคยคาดหวังหรือจะยอมรับถ้าคุณรู้ว่ามีการรวมไว้

การแก้ไขโหลที่ซ้ำกันกับ Maven ทำได้ดีที่สุดด้วยการรวมกันของmaven-dependency-pluginและmaven-enforcer-pluginภายใต้ Maven (หรือปลั๊กอินกราฟ Dependencyของ SBT จากนั้นเพิ่มขวดเหล่านั้นไปยังส่วนของ POM ระดับบนสุดของคุณหรือเป็นการนำเข้าอ้างอิง องค์ประกอบใน SBT (เพื่อลบการอ้างอิงเหล่านั้น)

โชคดี!


5
อาร์กิวเมนต์ verbose ช่วยฉันระบุขวดที่ให้ปัญหา ขอบคุณ
Virat Kadaru

6

ฉันได้ค้นพบว่าเมื่อใช้ JNI เรียกใช้วิธีการ Java จาก C ++ ถ้าคุณส่งพารามิเตอร์ไปยังวิธีการที่เรียกใช้ Java ในลำดับที่ไม่ถูกต้องคุณจะได้รับข้อผิดพลาดนี้เมื่อคุณพยายามใช้พารามิเตอร์ภายในวิธีการที่เรียกว่า จะไม่ถูกประเภท) ในตอนแรกฉันรู้สึกประหลาดใจว่า JNI ไม่ได้ทำการตรวจสอบนี้ให้คุณซึ่งเป็นส่วนหนึ่งของการตรวจสอบลายเซ็นคลาสเมื่อคุณเรียกใช้เมธอด แต่ฉันคิดว่าพวกเขาไม่ทำการตรวจสอบแบบนี้เพราะคุณอาจผ่านพารามิเตอร์ polymorphic และ สมมติว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่

ตัวอย่างรหัส C ++ JNI:

void invokeFooDoSomething() {
    jobject javaFred = FredFactory::getFred(); // Get a Fred jobject
    jobject javaFoo = FooFactory::getFoo(); // Get a Foo jobject
    jobject javaBar = FooFactory::getBar(); // Get a Bar jobject
    jmethodID methodID = getDoSomethingMethodId() // Get the JNI Method ID


    jniEnv->CallVoidMethod(javaFoo,
                           methodID,
                           javaFred, // Woops!  I switched the Fred and Bar parameters!
                           javaBar);

    // << Insert error handling code here to discover the JNI Exception >>
    //  ... This is where the IncompatibleClassChangeError will show up.
}

ตัวอย่างรหัส Java:

class Bar { ... }

class Fred {
    public int size() { ... }
} 

class Foo {
    public void doSomething(Fred aFred, Bar anotherObject) {
        if (name.size() > 0) { // Will throw a cryptic java.lang.IncompatibleClassChangeError
            // Do some stuff...
        }
    }
}

1
ขอบคุณสำหรับคำใบ้ ฉันมีปัญหาเดียวกันเมื่อโทรหาวิธี Java ด้วยอินสแตนซ์ที่ไม่ถูกต้อง (นี้) ที่ให้มา
พฤศจิกายน

5

ฉันมีปัญหาเดียวกันและต่อมาฉันก็พบว่าฉันกำลังเรียกใช้แอปพลิเคชันบน Java เวอร์ชัน 1.4 ในขณะที่แอปพลิเคชันนั้นรวบรวมในเวอร์ชั่น 6

ที่จริงแล้วสาเหตุของการมีไลบรารี่ที่ซ้ำกันหนึ่งอันอยู่ภายใน classpath และอีกอันรวมอยู่ในไฟล์ jar ที่อยู่ภายใน classpath


คุณไปถึงจุดต่ำสุดได้อย่างไร ฉันแน่ใจว่าฉันมีปัญหาที่คล้ายกัน แต่ไม่มีเบาะแสว่าจะติดตามห้องสมุดอ้างอิงใดที่จะถูกทำซ้ำ
beterthanlife

@beterthanlife เขียนสคริปต์ที่ค้นหาภายในไฟล์ jar ทั้งหมดเพื่อค้นหาคลาสที่ซ้ำ (ค้นหาด้วยชื่อเต็มของพวกเขาเช่นชื่อแพ็คเกจ) :)
Eng.Fouad

ตกลงใช้ NetBeans และ Maven-Shade ฉันคิดว่าฉันสามารถดูคลาสทั้งหมดที่มีการทำซ้ำและไฟล์ jar ที่พวกเขาอาศัยอยู่ไฟล์ jar เหล่านี้จำนวนมากที่ฉันไม่ได้อ้างอิงโดยตรงใน pom.xml ของฉันดังนั้นฉันคิดว่าพวกเขาต้อง ถูกรวมโดยการอ้างอิงของฉัน มีวิธีง่ายๆในการค้นหาว่าการพึ่งพาใดรวมอยู่ด้วยโดยไม่ต้องผ่านแต่ละไฟล์ pom ของการอ้างอิง? (โปรดอภัยความ
อิจฉาริษยา

@beterthanlife ถามคำถามใหม่เกี่ยวกับเรื่องนี้ได้ดีกว่า :)
Eng.Fouad

ฉันพบ jar ที่ซ้ำกันโดยดูที่กราฟการพึ่งพา gradle (./gradlew: <name>: dependencies) ดังนั้นฉันจึงพบผู้ร้ายที่ดึง lib เวอร์ชั่นเก่าเข้ามาในโครงการ
nyx

1

อีกสถานการณ์หนึ่งที่ข้อผิดพลาดนี้สามารถปรากฏขึ้นได้คือด้วย Emma Code Coverage

สิ่งนี้เกิดขึ้นเมื่อกำหนดวัตถุให้กับส่วนต่อประสาน ฉันเดาว่านี่เป็นสิ่งที่เกี่ยวข้องกับ Object ที่ถูกสร้างขึ้นมาและไม่สามารถใช้งานร่วมกับไบนารีได้อีกต่อไป

http://sourceforge.net/tracker/?func=detail&aid=3178921&group_id=177969&atid=883351

โชคดีที่ปัญหานี้ไม่ได้เกิดขึ้นกับ Cobertura ดังนั้นฉันจึงเพิ่ม cobertura-maven-plugin ในปลั๊กอินการรายงานของฉัน pom.xml


1

ฉันประสบกับปัญหานี้ในขณะที่ไม่ได้ปรับใช้และปรับใช้สงครามกับปลาแก้วอีกครั้ง โครงสร้างชั้นเรียนของฉันเป็นแบบนี้

public interface A{
}

public class AImpl implements A{
}

และมันก็เปลี่ยนเป็น

public abstract class A{
}

public class AImpl extends A{
}

หลังจากหยุดและเริ่มโดเมนใหม่ก็ทำงานได้ดี ฉันใช้ glassfish 3.1.43


1

ฉันมีเว็บแอปพลิเคชั่นที่ปรับใช้ได้อย่างสมบูรณ์แบบกับแมวทอมแครปในเครื่องของฉัน (8.0.20) อย่างไรก็ตามเมื่อฉันใส่ลงในสภาพแวดล้อม qa (tomcat - 8.0.20) มันยังคงให้ IncompatibleClassChangeError ฉันและมันก็บ่นว่าฉันขยายบนอินเทอร์เฟซ อินเทอร์เฟซนี้ถูกเปลี่ยนเป็นคลาสนามธรรม และฉันก็รวบรวมผู้ปกครองและชั้นเรียนเด็กและฉันยังคงได้รับปัญหาเดียวกัน ในที่สุดฉันต้องการที่จะแก้ปัญหาดังนั้นฉันเปลี่ยนรุ่นในผู้ปกครองเพื่อ x.0.1-SNAPSHOT แล้วรวบรวมทุกอย่างและตอนนี้มันทำงาน หากมีคนยังคงตีปัญหาหลังจากทำตามคำตอบที่ให้ไว้ที่นี่โปรดตรวจสอบให้แน่ใจว่ารุ่นใน pom.xml ของคุณนั้นถูกต้องเช่นกัน เปลี่ยนรุ่นเพื่อดูว่าใช้งานได้หรือไม่ ถ้าเป็นเช่นนั้นแก้ไขปัญหารุ่น


1

ฉันเชื่อว่าคำตอบของฉันจะเฉพาะเจาะจงของ Intellij

ฉันได้สร้างใหม่สะอาดแม้จะไปไกลเท่าที่จะลบ "ออก" และ "เป้าหมาย" dirs ด้วยตนเอง Intellij มี "แคชที่ไม่ถูกต้องและเริ่มต้นใหม่" ซึ่งบางครั้งจะล้างข้อผิดพลาดที่แปลก คราวนี้มันไม่ทำงาน รุ่นที่พึ่งพาทั้งหมดดูถูกต้องในเมนูการตั้งค่า -> โมดูล

คำตอบสุดท้ายคือการลบการพึ่งพาปัญหาจาก repo maven ท้องถิ่นของฉันด้วยตนเอง Bouncycastle รุ่นเก่าเป็นผู้ร้าย (ฉันรู้ว่าฉันเพิ่งเปลี่ยนรุ่นและนั่นจะเป็นปัญหา) และแม้ว่าเวอร์ชั่นเก่าจะไม่ปรากฏว่ามีสิ่งใดถูกสร้างขึ้นมามันแก้ปัญหาของฉันได้ ฉันใช้ Intellij เวอร์ชัน 14 แล้วอัปเกรดเป็น 15 ในระหว่างกระบวนการนี้


1

ในกรณีของฉันฉันพบข้อผิดพลาดนี้ด้วยวิธีนี้ pom.xmlของโครงการที่กำหนดไว้ของฉันสองอ้างอิงและA Bและทั้งสองAและการBพึ่งพาที่กำหนดไว้ในสิ่งประดิษฐ์เดียวกัน (เรียกว่าC) แต่รุ่นที่แตกต่างกันของมัน ( C.1และC.2) เมื่อสิ่งนี้เกิดขึ้นสำหรับแต่ละคลาสในCmaven สามารถเลือกรุ่นหนึ่งของคลาสจากสองเวอร์ชันเท่านั้น (ในขณะที่สร้างuber-jar ) มันจะเลือกรุ่น "ใกล้ที่สุด" ขึ้นอยู่กับกฎการไกล่เกลี่ยอ้างอิงและจะส่งคำเตือน"เรามีคลาสที่ซ้ำกัน ... "หากวิธีการ / ลายเซ็นชั้นเปลี่ยนไประหว่างรุ่นก็อาจทำให้เกิดjava.lang.IncompatibleClassChangeErrorข้อยกเว้นถ้ารุ่นที่ไม่ถูกต้องคือ ใช้ที่รันไทม์

ขั้นสูง: ถ้าAต้องใช้ v1 ของCและBต้องใช้ v2 ของCแล้วเราต้องย้าย CในAและB's ปอมไปสู่ความขัดแย้งระดับหลีกเลี่ยง (เรามีคำเตือนระดับที่ซ้ำกัน) เมื่อมีการสร้างโครงการสุดท้ายที่ขึ้นอยู่กับทั้งสองและAB


1

ในกรณีของข้อผิดพลาดปรากฏขึ้นเมื่อฉันเพิ่มห้องสมุดในใบสมัครของฉันนำไปใช้ในcom.nimbusds เกิดข้อยกเว้นด้านล่าง: Websphere 8.5

เกิดจาก: java.lang.IncompatibleClassChangeError: org.objectweb.asm.AnnotationVisitor

ทางออกคือการแยก asm jar ออกจากไลบรารี:

<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>5.1</version>
    <exclusions>
        <exclusion>
            <artifactId>asm</artifactId>
            <groupId>org.ow2.asm</groupId>
        </exclusion>
    </exclusions>
</dependency>

0

โปรดตรวจสอบว่ารหัสของคุณไม่ประกอบด้วยสองโครงการโมดูลที่มีชื่อคลาสและข้อกำหนดแพคเกจเดียวกัน เช่นนี้อาจเกิดขึ้นหากมีคนใช้ copy-paste เพื่อสร้างการใช้งานใหม่ของอินเทอร์เฟซตามการใช้งานก่อนหน้านี้


0

หากนี่เป็นบันทึกการเกิดขึ้นที่เป็นไปได้ของข้อผิดพลาดนี้ให้ทำดังนี้:

ฉันเพิ่งได้รับข้อผิดพลาดนี้ใน WAS (8.5.0.1) ระหว่างการโหลด CXF (2.6.0) ของการกำหนดค่าสปริง (3.1.1_release) ที่ BeanInstantiationException รีดขึ้น CXF ExtensionException เลื่อนขึ้น IncompatibleClassChangeError ตัวอย่างต่อไปนี้แสดงส่วนสำคัญของการติดตามสแต็ก:

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.apache.cxf.bus.spring.SpringBus]: Constructor threw exception; nested exception is org.apache.cxf.bus.extension.ExtensionException
            at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:162)
            at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:76)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990)
            ... 116 more
Caused by: org.apache.cxf.bus.extension.ExtensionException
            at org.apache.cxf.bus.extension.Extension.tryClass(Extension.java:167)
            at org.apache.cxf.bus.extension.Extension.getClassObject(Extension.java:179)
            at org.apache.cxf.bus.extension.ExtensionManagerImpl.activateAllByType(ExtensionManagerImpl.java:138)
            at org.apache.cxf.bus.extension.ExtensionManagerBus.<init>(ExtensionManagerBus.java:131)
            [etc...]
            at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
            ... 118 more

Caused by: java.lang.IncompatibleClassChangeError: 
org.apache.neethi.AssertionBuilderFactory
            at java.lang.ClassLoader.defineClassImpl(Native Method)
            at java.lang.ClassLoader.defineClass(ClassLoader.java:284)
            [etc...]
            at com.ibm.ws.classloader.CompoundClassLoader.loadClass(CompoundClassLoader.java:586)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:658)
            at org.apache.cxf.bus.extension.Extension.tryClass(Extension.java:163)
            ... 128 more

ในกรณีนี้วิธีแก้ไขคือเปลี่ยนลำดับ classpath ของโมดูลในไฟล์ war ของฉัน นั่นคือเปิดแอ็พพลิเคชันสงครามในคอนโซล WAS ภายใต้และเลือกโมดูลไคลเอ็นต์ ในการกำหนดค่าโมดูลตั้งค่าการโหลดคลาสเป็น "พาเรนต์สุดท้าย"

พบได้ในคอนโซล WAS:

  • Applicatoins -> ประเภทแอปพลิเคชัน -> แอปพลิเคชัน WebSphere Enterprise
  • คลิกลิงก์แสดงแอปพลิเคชันของคุณ (สงคราม)
  • คลิก "จัดการโมดูล" ใต้ส่วน "โมดูล"
  • คลิกลิงก์สำหรับโมดูลที่เกี่ยวข้อง
  • เปลี่ยน "ลำดับตัวโหลดคลาส" เป็น "(พาเรนต์สุดท้าย)"

0

จัดทำเอกสารสถานการณ์อื่นหลังจากใช้เวลานานเกินไป

ตรวจสอบให้แน่ใจว่าคุณไม่มี jar อ้างอิงที่มีคลาสที่มีคำอธิบายประกอบ EJB อยู่

เรามีไฟล์ jar ทั่วไปที่มี@localคำอธิบายประกอบ ชั้นเรียนนั้นถูกย้ายออกจากโปรเจ็กต์ทั่วไปและเข้าสู่โปรเจ็กต์ขวด ejb หลักของเรา โถ ejb ของเราและ jar ทั่วไปของเรานั้นถูกรวมไว้ในหู เวอร์ชันของการพึ่งพา jar ทั่วไปของเราไม่ได้รับการอัพเดต ดังนั้น 2 คลาสที่พยายามเป็นบางอย่างที่มีการเปลี่ยนแปลงที่เข้ากันไม่ได้


0

จากทั้งหมดที่กล่าวมา - ไม่ว่าจะด้วยเหตุผลใดก็ตามฉันกำลังทำสิ่งปลูกสร้างขนาดใหญ่และเริ่มรับสิ่งนี้ ฉันเปลี่ยนชื่อแพ็คเกจของฉันแล้ว หวังว่าจะช่วย


0

ด้วยเหตุผลบางอย่างยกเว้นเดียวกันยังจะถูกโยนทิ้งเมื่อใช้ JNI และผ่านอาร์กิวเมนต์ jclass แทน jobject Call*Method()เมื่อเรียก

คล้ายกับคำตอบจาก Ogre Psalm33

void example(JNIEnv *env, jobject inJavaList) {
    jclass class_List = env->FindClass("java/util/List");

    jmethodID method_size = env->GetMethodID(class_List, "size", "()I");
    long size = env->CallIntMethod(class_List, method_size); // should be passing 'inJavaList' instead of 'class_List'

    std::cout << "LIST SIZE " << size << std::endl;
}

ฉันรู้ว่ามันช้าไปหน่อยที่จะตอบคำถามนี้หลังจาก 5 ปีหลังจากถูกถาม แต่นี่เป็นหนึ่งในเพลงฮิตอันดับต้น ๆ ในการค้นหาjava.lang.IncompatibleClassChangeErrorดังนั้นฉันต้องการบันทึกกรณีพิเศษนี้


0

การเพิ่ม 2 เซนต์ของฉันหากคุณใช้สกาล่าและ sbt และการบันทึกสกาล่าเป็นการพึ่งพาซึ่งอาจเกิดขึ้นได้เนื่องจากเวอร์ชันก่อนหน้าของการบันทึกล็อกสกาล่ามีชื่อ ชื่อที่นำไปสู่ข้อผิดพลาดรันไทม์ขณะเรียกใช้แอปพลิเคชันสกาล่า


0

สาเหตุเพิ่มเติมของปัญหานี้คือถ้าคุณInstant Runเปิดใช้งานสำหรับ Android Studio

การแก้ไข

Instant Runหากคุณพบว่าคุณเริ่มได้รับข้อผิดพลาดนี้ปิด

  1. การตั้งค่าหลักของ Android Studio
  2. Build, Execution, Deployment
  3. เรียกใช้ทันที
  4. ยกเลิกการเลือก "เปิดใช้งานการเรียกใช้ทันที ... "

ทำไม

Instant Runปรับเปลี่ยนสิ่งต่าง ๆ จำนวนมากในระหว่างการพัฒนาเพื่อทำให้การอัปเดตแอปที่ทำงานอยู่ของคุณเร็วขึ้น ดังนั้นจึงเรียกใช้ทันที เมื่อใช้งานได้จริงมันมีประโยชน์จริงๆ อย่างไรก็ตามเมื่อปัญหาเช่นการประท้วงนี้สิ่งที่ดีที่สุดที่ต้องทำคือการปิดInstant Runจนกว่า Android Studio รุ่นถัดไปจะออก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.