การรวมไหทั้งหมดในไดเร็กทอรีภายใน Java classpath


1018

มีวิธีรวมไฟล์ jar ทั้งหมดในไดเร็กทอรีใน classpath หรือไม่?

ฉันพยายามjava -classpath lib/*.jar:. my.package.Programแล้วและไม่สามารถหาไฟล์คลาสที่อยู่ในไหเหล่านั้นได้ ฉันต้องเพิ่มไฟล์ jar แต่ละไฟล์ใน classpath แยกกันหรือไม่?


3
ขอโทษฉันไม่เคยยอมรับสิ่งนี้ ควรเป็นวิกิชุมชน ไม่เคยใช้หนึ่งในคำตอบที่ให้ ฉันเชื่อว่าฉันสร้างเชลล์สคริปต์ที่เพิ่งสแกน lib / directory และสร้าง classpath จากการแยกชื่อไฟล์
Chris Serra

มีข้อบกพร่องบางอย่างในคุณสมบัติ Java ใหม่นี้เพราะมันไม่ทำงานตามที่อธิบายไว้ ฉันเลิกและใช้ Ant เพื่อหลีกเลี่ยงปัญหาดังที่อธิบายไว้ในคำตอบข้อใดข้อหนึ่ง
Alex R


1
มีปัญหากับการประมวลผลสัญลักษณ์ใน Windows stackoverflow.com/questions/11607873/…
Mykhaylo Adamovych

6
คำตอบสั้น ๆ : (1) วาง.jarส่วน (2) ต้องมีอย่างน้อย 2 ส่วนโดยคั่นด้วย;บน Windows (ซึ่งมักจะอยู่:ที่อื่น) ตัวอย่างเช่น:java -classpath ".;lib/*" Program
Evgeni Sergeev

คำตอบ:


1159

ใช้ Java 6 หรือใหม่กว่าตัวเลือก classpath รองรับ wildcards หมายเหตุดังต่อไปนี้:

  • ใช้เครื่องหมายคำพูดตรง ( ")
  • ใช้*ไม่ได้*.jar

ของ windows

java -cp "Test.jar;lib/*" my.package.MainClass

ยูนิกซ์

java -cp "Test.jar:lib/*" my.package.MainClass

นี้จะคล้ายกับ Windows แต่ใช้แทน: ;หากคุณไม่สามารถใช้ไวด์การ์ดbashอนุญาตให้ใช้ไวยากรณ์ต่อไปนี้ (ซึ่งlibเป็นไดเร็กทอรีที่มีไฟล์เก็บถาวร Java ทั้งหมด):

java -cp $(echo lib/*.jar | tr ' ' ':')

(โปรดทราบว่าการใช้ classpath ไม่เข้ากันกับ-jarตัวเลือกดูเพิ่มเติม: เรียกใช้ไฟล์ jar ที่มีหลายคลาสพา ธ ของไลบรารีจากพรอมต์คำสั่ง )

ทำความเข้าใจสัญลักษณ์แทน

จากเอกสารClasspath :

รายการเส้นทางระดับสามารถมีตัวอักษร basename สัญลักษณ์แทน*ซึ่งถือว่าเทียบเท่ากับการระบุรายชื่อของไฟล์ทั้งหมดในไดเรกทอรีที่มีนามสกุลหรือ.jar .JARตัวอย่างเช่นรายการพา ธ คลาสfoo/*ระบุไฟล์ JAR ทั้งหมดในไดเร็กทอรีที่ชื่อ foo รายการ classpath ประกอบด้วยการ*ขยายไปยังรายการไฟล์ jar ทั้งหมดในไดเร็กทอรีปัจจุบัน

รายการคลาสพา ธ ที่มี*จะไม่ตรงกับไฟล์คลาส เพื่อให้ตรงกับทั้งการเรียนและไฟล์ JAR ใน foo ไดเรกทอรีเดียวใช้อย่างใดอย่างหนึ่ง หรือfoo;foo/* foo/*;fooลำดับที่เลือกจะกำหนดว่าfooโหลดคลาสและทรัพยากรในก่อนไฟล์ JAR fooหรือในทางกลับกัน

ไดเรกทอรีย่อยจะไม่ถูกค้นหาซ้ำ ตัวอย่างเช่นfoo/*รูปลักษณ์สำหรับไฟล์ JAR เฉพาะในfooไม่ได้อยู่ในfoo/bar, foo/bazฯลฯ

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

การขยาย wildcard เสร็จสิ้นก่อนที่จะมีการเรียกใช้วิธีหลักของโปรแกรมแทนการมาสายในระหว่างกระบวนการโหลดคลาสเอง แต่ละองค์ประกอบของเส้นทางคลาสอินพุตที่มีอักขระตัวแทนจะถูกแทนที่ด้วยลำดับ (อาจว่างเปล่า) ขององค์ประกอบที่สร้างขึ้นโดยการแจกแจงไฟล์ JAR ในไดเรกทอรีที่มีชื่อ ตัวอย่างเช่นถ้าไดเรกทอรีfooมีa.jar, b.jarและc.jarแล้วเส้นทางการเรียนfoo/*มีการขยายเข้าไปในและสตริงที่จะเป็นมูลค่าของทรัพย์สินระบบfoo/a.jar;foo/b.jar;foo/c.jar java.class.path

CLASSPATHตัวแปรสภาพแวดล้อมไม่ได้รับการรักษาใด ๆ ที่แตกต่างจาก-classpath(หรือ-cp) ตัวเลือกบรรทัดคำสั่ง นั่นคือ wildcard ได้รับเกียรติในทุกกรณี อย่างไรก็ตามอักขระตัวแทนเส้นทางคลาสไม่ได้รับเกียรติในClass-Path jar-manifestส่วนหัว

หมายเหตุ: เนื่องจากบั๊กที่รู้จักใน java 8 ตัวอย่าง windows ต้องใช้แบ็กสแลชก่อนหน้ารายการที่มีเครื่องหมายดอกจันต่อท้าย: https://bugs.openjdk.java.net/browse/JDK-8131329


2
คุณลักษณะดังกล่าวได้รับการบันทึกไว้ไม่ดีและดูเหมือนว่าจะต้องได้รับความพึงพอใจก่อนเงื่อนไขบางอย่างที่ไม่ชัดเจนเพื่อให้สามารถทำงานได้ตามที่ต้องการ
Alex R

1
+1 สำหรับเคล็ดลับ bash / tr ล่าสุด Java / JamVM ที่นี่ไม่ชอบ wildcard สำหรับเส้นทางที่อยู่นอกไดเรกทอรีทำงาน แต่อ้างอิง JAR แต่ละตัวโดยใช้ shell wildcard + ใช้trงานได้!
Supr

1
ฉันมีคำสั่งjava -classpath /jars/*:/anotherJarsDir/* com.test.MyClassโดยไม่ใส่เครื่องหมายอัญประกาศ ฉันสงสัยว่าทำไมเชลล์ไม่ขยายและแก้ไขข้อผิดพลาด?
yellavon

3
ยังไม่ได้ใช้~ใน -cp
Sohail Si

1
ตัวอย่าง windows ของคุณไม่สามารถใช้กับ java 8 หรือรุ่นก่อนหน้า แต่ใช้กับ classpath นี้: Test.jar; lib \ * ... forward slash ไม่เป็นไรยกเว้นเมื่อก่อนหน้าเครื่องหมายดอกจันและอีกสองสาม ... ดูbugs.openjdk java.net/browse/JDK-8131329
philwalk

226

ภายใต้ Windows ใช้งานได้:

java -cp "Test.jar;lib/*" my.package.MainClass

และสิ่งนี้ไม่ทำงาน:

java -cp "Test.jar;lib/*.jar" my.package.MainClass

สังเกตเห็นขวด * ดังนั้นสัญลักษณ์แทน * ควรใช้เพียงอย่างเดียว


บน Linux งานต่อไปนี้:

java -cp "Test.jar:lib/*" my.package.MainClass

ตัวคั่นเป็นเครื่องหมายโคลอนแทนเครื่องหมายอัฒภาค


17
คำตอบที่สมบูรณ์แบบ 2 สิ่งสำคัญที่ควรสังเกต: 1) ใช้เครื่องหมายคำพูดและ 2) ใช้ * เท่านั้นไม่ใช่ * .jar
Wim Deblauwe

4
หนึ่งปีกับอีก 8 เดือนต่อมาการแก้ไขที่ฉันทำเพื่อรวมเวอร์ชัน UNIX ช่วยฉันอีกครั้ง :) ตลกว่ามันจะไม่รู้จักไฟล์ jar ของฉันที่มีแต่เฉพาะกับ*.jar *
jmort253

ฉันพบว่าลำดับของ classpaths มีความสำคัญ (แต่ฉันไม่รู้ว่าทำไม) ฉันได้รับข้อผิดพลาดจนกว่าฉันจะเปลี่ยนลำดับของ classpaths
user13107

@ jmort253 สิ่งนี้ไม่ใช่เชลล์ * ที่ขยาย แต่สัญลักษณ์แทนคือจาวาแยกคลาสพา ธ ดู * และเติมสัญลักษณ์แทน
เซบาสเตียน

1
@SebastianGodelet - ใช่นั่นเป็นเพียงฉันสับสนระหว่างสัญลักษณ์ตัวแทน Regex และสัญลักษณ์นี้ซึ่งไม่เหมือนกันฉันเดา ส่วนใหญ่สิ่งที่บันทึกฉันจะทราบความแตกต่างระหว่าง:บนแพลตฟอร์มเดียวและ;ในที่อื่น ๆ :) ฉันคอมไพล์กับ Java จากบรรทัดคำสั่งประมาณปีละครั้งพอที่จะไม่จำได้ว่าบ่อยครั้งพอที่จะน่ารำคาญ
jmort253

67

เราแก้ไขปัญหานี้โดยการปรับใช้ไฟล์ jar หลักmyapp.jarซึ่งมีไฟล์ Manifest ( Manifest.mf) ที่ระบุ classpath ด้วย jars ที่จำเป็นอื่น ๆ ซึ่งจะนำไปใช้งานข้างๆมัน ในกรณีนี้คุณจะต้องประกาศjava -jar myapp.jarเมื่อเรียกใช้รหัสเท่านั้น

ดังนั้นถ้าคุณปรับใช้หลักjarในไดเรกทอรีบางส่วนแล้วใส่ขวดที่ต้องพึ่งพาลงในlibโฟลเดอร์ด้านล่างรายการจะมีลักษณะดังนี้:

Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar

หมายเหตุ: นี่เป็นแพลตฟอร์มอิสระ - เราสามารถใช้ไหเดียวกันเพื่อเปิดตัวบนเซิร์ฟเวอร์ UNIX หรือบนพีซี Windows


สิ่งนี้ดูเหมือนจะใช้ได้กับคนจำนวนมากอย่างไรก็ตาม Java ดูเหมือนจะไม่สนใจรายการ Class-Path ในไฟล์ Manifest ที่นี่ เราไม่สามารถเรียกใช้แอปพลิเคชันโดยไม่เพิ่ม "lib / *" ลงใน classpath ด้วยตนเองโดยใช้ -cp ความคิดใด ๆ
Raku

6
คำตอบของ oxbow_lakes ไม่ถูกต้องทั้งหมด สิ่ง Class-Path เป็นเกียรติ (และเฉพาะที่ได้รับเกียรติ; -cp / -classpath จะถูกละเว้น!) ถ้าคุณเริ่มขวดนี้ด้วย java -jar myapp.jar ฉันเข้าใจว่า oxbow_lakes หมายถึงการเขียนว่าเมื่อเขาเขียน 'java -classpath myapp.jar'
rzwitserloot

47

วิธีแก้ปัญหาของฉันใน Ubuntu 10.04 โดยใช้ java-sun 1.6.0_24 มี jars ทั้งหมดในไดเรกทอรี "lib":

java -cp.: lib / * my.main.Class

หากสิ่งนี้ล้มเหลวคำสั่งต่อไปนี้ควรใช้งานได้ (พิมพ์ * .jars ทั้งหมดในไดเร็กทอรี lib ไปยัง classpath param)

java -cp $ (สำหรับ i ใน lib / *. jar; do echo -n $ i:; เสร็จแล้ว) my.main.Class

4
ข้อความตลก java -cp lib / * my.main.Class จะล้มเหลวเสมอเนื่องจากการขยายตัวของเชลล์ glob ของ lib / * ในขณะที่ java -cp.: lib / * my.main.Class จะไม่ได้เพราะ: lib / * ไม่ใช่ glob ที่ถูกต้อง เส้นทาง. ใช้เวลาสักครู่เพื่อทราบว่า
albfan

1
สิ่งนี้ไม่ทำงาน ลินุกซ์จะขยาย คุณสามารถลอง: java -cp '.: lib / ' และใช้งานได้ดี (จดเครื่องหมายคำพูดเดี่ยว! มันจะไม่ทำงานกับเครื่องหมายคำพูดคู่!) ที่จริงแล้ว.: lib / * อาจใช้งานได้หากไม่ได้เป็นรูปกลมที่ถูกต้องเนื่องจากลำไส้ใหญ่ แต่มันให้ความรู้สึกที่ไม่ดีนัก ฉันจะเพิ่มคำพูด เครื่องหมายคำพูดเดี่ยวบอกว่าทุบตีเพื่อไม่ให้สัมผัสส่วนใดส่วนหนึ่งของเนื้อหา
rzwitserloot

ไม่สำคัญ (ในบริบทนี้) หากคุณใช้เครื่องหมายคำพูดเดี่ยวหรือคู่ คุณต้องการป้องกันไม่ให้เชลล์ขยาย (กลม) * นั่นคือทั้งหมด และส่งผ่านข้อความ "lib / *" ไปยัง JVM โดยคร่าวๆดังนั้น VM จะจดจำสิ่งนี้ว่าเป็น "รูปแบบพิเศษ" และค้นหาไฟล์ jar ด้วยตัวเอง
Angel O'Sphere

36

คำตอบสั้น ๆ : java -classpath lib/*:. my.package.Program

Oracle ให้เอกสารเกี่ยวกับการใช้สัญลักษณ์ใน classpaths ที่นี่สำหรับ Java 6และที่นี่สำหรับ Java 7ภายใต้หัวข้อในส่วนสัญลักษณ์แทนเส้นทางระดับความเข้าใจ (ขณะที่ฉันเขียนสิ่งนี้ทั้งสองหน้ามีข้อมูลเดียวกัน) นี่เป็นบทสรุปของไฮไลท์

  • โดยทั่วไปเมื่อต้องการรวม JARs ทั้งหมดในไดเรกทอรีที่กำหนดคุณสามารถใช้อักขระตัวแทน*( ไม่ใช่ *.jar )

  • อักขระตัวแทนตรงกับ JAR ไม่ใช่ไฟล์คลาส ในการรับคลาสทั้งหมดในไดเรกทอรีเพียงแค่จบรายการ classpath ที่ชื่อไดเรกทอรี

  • ตัวเลือกสองตัวด้านบนสามารถรวมกันเพื่อรวมไฟล์ JAR และไฟล์คลาสทั้งหมดในไดเรกทอรีและใช้กฎการจัดลำดับความสำคัญคลาสพา ธ ปกติ เช่น-cp /classes;/jars/*

  • อักขระตัวแทนจะไม่ค้นหา JAR ในไดเรกทอรีย่อย

  • สัญลักษณ์แสดงหัวข้อย่อยข้างต้นเป็นจริงหากคุณใช้CLASSPATHคุณสมบัติของระบบหรือการตั้งค่าสถานะบรรทัดคำสั่ง-cpหรือ -classpathอย่างไรก็ตามหากคุณใช้Class-Pathส่วนหัวรายการ JAR (อย่างที่คุณอาจทำกับไฟล์ ant build) wildcard จะไม่ได้รับเกียรติ

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


ปัญหาของฉันกับ lib / *. jar มากกว่า lib / * ขอบคุณมากมันทำให้มันคงที่ ฉันสังเกตเห็นว่ามีความแตกต่างระหว่าง: และ; แต่นั่นอาจเป็นการทดสอบที่เปลี่ยนแปลงหลายอย่างในเวลาเดียวกันของฉัน
Eyad Ebrahim

ขอขอบคุณที่เน้นความแตกต่างระหว่าง * และ * .jar
burakhan alkan

36

Windows :

 java -cp file.jar;dir/* my.app.ClassName

Linux :

 java -cp file.jar:dir/* my.app.ClassName

เตือน:
- ตัวคั่นพา ธ ของWindowsคือ;
- ตัวคั่นพา ธ ของLinuxคือ:
- ใน Windows หากอาร์กิวเมนต์ cp ไม่มีช่องว่างสีขาว "เครื่องหมายคำพูด" เป็นตัวเลือก


ตัวอย่าง windows ไม่ทำงานสำหรับ java 8 และรุ่นก่อนหน้า: ดูbugs.openjdk.java.net/browse/JDK-8131329
philwalk

อาจจะไม่ทำงานกับ JDK แบบเปิดฉันจะทดสอบสิ่งนี้และฉันจะพูดถึงที่นี่
Wender

ขออภัยฉันทำการทดสอบด้วย HotSpot และฉันคิดว่าใช้งานได้กับ openjdk
Wender

Oracle Java ภายใต้ windows ต้องการแบ็กสแลชก่อนหน้าเครื่องหมายดอกจันมากกว่าสแลชสแลชแม้ว่าฉันจะไม่ได้ทดสอบจาวาเวอร์ชันล่าสุดหรือเวอร์ชันอื่นสำรอง
philwalk

ไม่ทำงานบน macos
Greyshack

34

สำหรับฉันงานนี้ใน windows

java -cp "/lib/*;" sample

สำหรับ linux

java -cp "/lib/*:" sample

ฉันใช้Java 6


ตัวอย่าง windows ดูเหมือนว่าจะใช้งานได้กับ java 6 อาจเป็น java 7 แต่ไม่ใช่สำหรับ java 8 (ดูbugs.openjdk.java.net/browse/JDK-8131329 )
philwalk

ใช้งานได้กับ java 8 ใน linux
Jonathan Drapeau

29

คุณสามารถลอง java -Djava.ext.dirs=jarDirectory http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html

ไดเร็กทอรีสำหรับไหภายนอกเมื่อรันจาวา


3
งานนี้ แต่ระวังส่ง-Djava.ext.dirs=ก่อน-jar
Giovanni Funchal

5
java.ext.dirs จะทำงานแตกต่างจาก jar ปกติใน classpath มันมีลำดับความสำคัญสูงกว่าและได้รับอนุญาตซึ่งจะสามารถแทนที่คลาสใดใน bootstamp (rt.jar) อย่างใดอย่างหนึ่ง
Dennis C

ขอบคุณ ใน 'java รุ่น "1.8.0_221" Java (TM) SE สภาวะแวดล้อมรันไทม์ (บิลด์ 1.8.0_221-b27) เซิร์ฟเวอร์ Java HotSpot (TM) 64- บิตเซิร์ฟเวอร์ VM (สร้าง 25.221-b27, โหมดผสม)' เฉพาะรุ่น -D นี้ ของการผ่านใน classpath ทำงาน รูปแบบดั้งเดิมไม่ได้
Matt Campbell เมื่อ

23

ถูกต้อง :

java -classpath "lib/*:." my.package.Program

ไม่ถูกต้อง:

java -classpath "lib/a*.jar:." my.package.Program
java -classpath "lib/a*:."     my.package.Program
java -classpath "lib/*.jar:."  my.package.Program
java -classpath  lib/*:.       my.package.Program

9

ถ้าคุณต้องการจริงๆเพื่อระบุไฟล์ทั้งหมดในขวดแบบไดนามิกคุณสามารถใช้เชลล์สคริปต์หรือApache Ant มีโครงการทั่วไปที่เรียกว่าCommons Launcherซึ่งโดยทั่วไปแล้วจะช่วยให้คุณระบุสคริปต์เริ่มต้นของคุณเป็นไฟล์ ant build (ถ้าคุณเห็นสิ่งที่ฉันหมายถึง)

จากนั้นคุณสามารถระบุสิ่งที่ชอบ:

<path id="base.class.path">
    <pathelement path="${resources.dir}"/>
    <fileset dir="${extensions.dir}" includes="*.jar" />
    <fileset dir="${lib.dir}" includes="*.jar"/>
</path>

ในไฟล์ build build ของคุณซึ่งจะเรียกทำงานแอ็พพลิเคชันของคุณด้วย classpath ที่ถูกต้อง



8

โปรดทราบว่าการขยายสัญลักษณ์แทนถูกทำลายสำหรับ Java 7 บน Windows

ตรวจสอบปัญหา StackOverflow นี้สำหรับข้อมูลเพิ่มเติม

วิธีแก้ปัญหาคือการใส่เครื่องหมายอัฒภาคไว้หลังสัญลักษณ์แทน java -cp "somewhere/*;"


6

ถึงผู้เกี่ยวข้อง,

ฉันพบพฤติกรรมแปลก ๆ นี้ใน Windows ภายใต้ MSYS / MinGW shell

ผลงาน:

$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.java

ใช้งานไม่ได้:

$ javac -cp 'c:\Programs\COMSOL44\plugins\*' Reclaim.java
javac: invalid flag: c:\Programs\COMSOL44\plugins\com.comsol.aco_1.0.0.jar
Usage: javac <options> <source files>
use -help for a list of possible options

ฉันค่อนข้างแน่ใจว่าสัญลักษณ์แทนไม่ได้ถูกขยายโดยเชลล์เพราะเช่น

$ echo './*'
./*

(พยายามกับโปรแกรมอื่นด้วยแทนที่จะเป็นแบบในตัวechoด้วยผลลัพธ์เดียวกัน)

ฉันเชื่อว่ามันjavacกำลังพยายามที่จะขยายมันและมันจะทำงานแตกต่างกันว่ามีอัฒภาคในการโต้แย้งหรือไม่ อันดับแรกอาจพยายามขยายอาร์กิวเมนต์ทั้งหมดที่มีลักษณะเป็นเส้นทาง และจากนั้นมันก็จะแยกพวกเขาด้วย-cpการใช้เพียงโทเค็นต่อไปนี้ (โปรดทราบว่าcom.comsol.aco_1.0.0.jarเป็น JAR ตัวที่สองในไดเรกทอรีนั้น) นั่นคือการคาดเดาทั้งหมด

นี่คือ

$ javac -version
javac 1.7.0

5

โซลูชันด้านบนทั้งหมดใช้งานได้ดีหากคุณพัฒนาและรันแอปพลิเคชัน Java นอก IDE ใด ๆ เช่น Eclipse หรือ Netbeans

หากคุณใช้ Windows 7 และใช้ Eclipse IDE เพื่อการพัฒนาใน Java คุณอาจพบปัญหาหากใช้ Command Prompt เพื่อเรียกใช้ไฟล์คลาสที่สร้างขึ้นภายใน Eclipse

เช่นซอร์สโค้ดของคุณใน Eclipse มีลำดับชั้นแพ็คเกจดังนี้: edu.sjsu.myapp.Main.java

คุณมี json.jar เป็นการพึ่งพาภายนอกสำหรับ Main.java

เมื่อคุณลองเรียกใช้ Main.java จากภายใน Eclipse มันจะทำงานโดยไม่มีปัญหาใด ๆ

แต่เมื่อคุณลองเรียกใช้งานโดยใช้ Command Prompt หลังจากคอมไพล์ Main.java ใน Eclipse มันจะถ่ายภาพข้อผิดพลาดแปลก ๆ ที่บอกว่า "ClassNotDef Error blah blah"

ฉันคิดว่าคุณอยู่ในไดเรกทอรีการทำงานของซอร์สโค้ดของคุณ !!

ใช้ไวยากรณ์ต่อไปนี้เพื่อเรียกใช้จากพรอมต์คำสั่ง:

  1. javac -cp ".; json.jar" Main.java

  2. java -cp ".; json.jar" edu.sjsu.myapp.Main

    อย่าพลาด ข้างบน]

นี่เป็นเพราะคุณวาง Main.java ไว้ในแพ็คเกจ edu.sjsu.myapp และ java.exe จะค้นหารูปแบบที่แน่นอน

หวังว่ามันจะช่วย !!


4

สำหรับราคา windows จำเป็นต้องมีและ; ควรใช้เป็นตัวคั่น เช่น:

java -cp "target\\*;target\\dependency\\*" my.package.Main

4

แบบสั้น: หากหลักของคุณอยู่ในขวดคุณอาจต้องใช้ '-jar pathTo / yourJar / YourJarsName.jar' ประกาศอย่างชัดเจนเพื่อให้มันทำงานได้ (แม้ว่า 'YourJarsName.jar' จะอยู่ใน classpath) (หรือ แสดงเพื่อตอบคำถามเดิมที่ถูกถามเมื่อ 5 ปีที่แล้ว: คุณไม่จำเป็นต้องประกาศซ้ำแต่ละขวดอย่างชัดเจน แต่ดูเหมือนว่าแม้จะมี java6 คุณต้องประกาศใหม่ขวดของคุณเอง ... )


แบบยาว: (ฉันได้ทำสิ่งนี้อย่างชัดเจนจนถึงจุดที่ฉันหวังว่าแม้กระทั่ง interlopers ของ java สามารถใช้สิ่งนี้ได้)

ชอบมากที่นี่ฉันใช้ eclipse เพื่อส่งออกไห: (ไฟล์ -> ส่งออก -> 'ไฟล์ JAR Runnable') ข้อเสนอ eclipse (Juno) ของข้อเสนอมีสามตัวเลือก:

opt1: "Extract required libraries into generated JAR"
opt2: "Package required libraries into generated JAR"
opt3: "Copy required libraries into a sub-folder next to the generated JAR"

โดยทั่วไปแล้วฉันจะใช้ opt2 (และ opt1 แตกหักอย่างแน่นอน) อย่างไรก็ตามรหัสท้องถิ่นในขวดที่ฉันใช้ฉันค้นพบตัวแบ่งด้วยเคล็ดลับ "jarinjar" ที่มีประโยชน์ซึ่ง eclipse จะยกระดับเมื่อคุณเลือกตัวเลือกนั้น แม้หลังจากรู้ตัวว่าฉันต้องการ opt3 แล้วค้นหารายการ StackOverflow นี้ฉันยังต้องใช้เวลาพอสมควรในการหาวิธีเริ่มต้นหลักนอก eclipse ดังนั้นนี่คือสิ่งที่ใช้ได้ผลกับฉันเพราะมันมีประโยชน์สำหรับผู้อื่น ...


หากคุณตั้งชื่อ jar ของคุณ: "fooBarTheJarFile.jar" และทั้งหมดถูกตั้งค่าให้ส่งออกไปยัง dir: "/ theFully / ที่มีคุณสมบัติครบถ้วนPath / toYourChosenDir"

(หมายถึงฟิลด์ 'ส่งออกปลายทาง' จะอ่าน: '/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar')

หลังจากที่คุณกดปุ่มเสร็จคุณจะพบ eclipse และใส่ไลบรารี่ทั้งหมดลงในโฟลเดอร์ชื่อ 'fooBarTheJarFile_lib' ภายในไดเรกทอรีส่งออกนั้นให้สิ่งที่คุณต้องการ:

/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar01.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar02.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar03.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar04.jar

จากนั้นคุณสามารถเปิดจากที่ใดก็ได้ในระบบของคุณด้วย:

java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" -jar  /theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar   package.path_to.the_class_with.your_main.TheClassWithYourMain

(สำหรับ Java Newbies: 'package.path_to.the_class_with.your_main' เป็นพา ธ แพ็กเกจที่ประกาศซึ่งคุณจะพบที่ด้านบนของไฟล์ 'TheClassWithYourMain.java' ที่มีเนื้อหา 'main (String [] args) .} 'ที่คุณต้องการเรียกใช้จาก java ภายนอก)


ข้อผิดพลาดที่ควรสังเกต: คือการมี 'fooBarTheJarFile.jar' อยู่ในรายการขวดบน classpath ที่คุณประกาศไม่เพียงพอ คุณต้องประกาศ '-jar' อย่างชัดเจนและประกาศตำแหน่งของ jar นั้นอีกครั้ง

เช่นการแบ่งนี้:

 java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*"  somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain

ปรับปรุงใหม่ด้วยเส้นทางญาติ:

cd /theFully/qualifiedPath/toYourChosenDir/;
BREAKS:  java -cp "fooBarTheJarFile_lib/*"                                package.path_to.the_class_with.your_main.TheClassWithYourMain    
BREAKS:  java -cp ".;fooBarTheJarFile_lib/*"                              package.path_to.the_class_with.your_main.TheClassWithYourMain   
BREAKS:  java -cp ".;fooBarTheJarFile_lib/*"   -jar                       package.path_to.the_class_with.your_main.TheClassWithYourMain   
WORKS:   java -cp ".;fooBarTheJarFile_lib/*"   -jar  fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain   

(ใช้รุ่นจาวา "1.6.0_27"; ผ่าน OpenJDK 64- บิตเซิร์ฟเวอร์ VM บน Ubuntu 12.04)


3

วิธีเดียวที่ฉันรู้วิธีที่จะทำมันเป็นรายบุคคลเช่น:

setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.

หวังว่าจะช่วย!


นี่อาจเป็นทางเดียวใน '08 แต่ไม่ใช่อีกต่อไป
simo.3792

นี่ไม่ใช่สิ่งที่เลวร้ายที่สุด มันเป็นแฮ็ค แต่ฉันมีชุดนี้ใน bashrc ของฉันfor jar in $(ls $HOME/bin/*.jar); do export CLASSPATH=$jar:$CLASSPATH; done
Devon Peticolas


2

คุณต้องเพิ่มทั้งหมดแยกต่างหาก หรือถ้าคุณต้องการระบุไดเรกทอรีจริงๆคุณสามารถ unjar ทุกอย่างลงใน dir เดียวและเพิ่มลงใน classpath ของคุณ ฉันไม่แนะนำวิธีการนี้ แต่คุณเสี่ยงต่อปัญหาที่แปลกประหลาดในการกำหนดเวอร์ชันพา ธ และการจัดการไม่ได้


3
นี่อาจเป็นทางเดียวใน '08 แต่ไม่ใช่อีกต่อไป
simo.3792

2

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

 libDir2Scan4jars="../test";cp=""; for j in `ls ${libDir2Scan4jars}/*.jar`; do if [ "$j" != "" ]; then cp=$cp:$j; fi; done; echo $cp| cut -c2-${#cp} > .tmpCP.tmp; export tmpCLASSPATH=`cat .tmpCP.tmp`; if [ "$tmpCLASSPATH" != "" ]; then echo .; echo "classpath set, you can now use  ~>         java -cp \$tmpCLASSPATH"; echo .; else echo .; echo "Error please check libDir2Scan4jars path"; echo .; fi; 

สคริปท์สำหรับลีนุกซ์, อาจมีอันที่คล้ายกันสำหรับ windows ด้วย หากมีการระบุไดเรกทอรีที่เหมาะสมเป็นอินพุตของ "libDir2Scan4jars"; สคริปต์จะสแกนไหทั้งหมดและสร้างสตริงพา ธ คลาสและส่งออกไปยังตัวแปร env "tmpCLASSPATH"


2

macOS โฟลเดอร์ปัจจุบัน

สำหรับ Java 13 บนmacOS Mojave ...

หากทุก.jarไฟล์ในโฟลเดอร์เดียวกันใช้cdที่จะทำให้คุณไดเรกทอรีการทำงานปัจจุบัน pwdตรวจสอบกับ

สำหรับ-classpathคุณจะต้องแสดงรายการไฟล์ JARสำหรับแอปของคุณก่อน ใช้อักขระโคลอน:เป็นตัวคั่นผนวกเครื่องหมายดอกจัน*เพื่อรับไฟล์ JAR อื่นทั้งหมดภายในโฟลเดอร์เดียวกัน สุดท้ายผ่านชื่อแพคเกจเต็มรูปแบบของการเรียนด้วยวิธีการmain

ตัวอย่างเช่นสำหรับแอปในไฟล์ JAR ที่ตั้งชื่อmy_app.jarด้วยmainวิธีการในคลาสที่มีชื่อAppในแพ็คเกจที่มีชื่อcom.exampleข้างๆ jars ที่จำเป็นในโฟลเดอร์เดียวกัน:

java -classpath my_app.jar:* com.example.App

ไม่ทำงานกับ java 8
Greyshack

1

คิดว่าไฟล์ jar เป็นรูทของโครงสร้างไดเร็กทอรี ใช่คุณต้องเพิ่มแยกทั้งหมด


1

ตั้งค่า classpath ด้วยวิธีที่เหมาะสมกับหลาย ๆ ไหและไฟล์คลาสของไดเรกทอรีปัจจุบัน

CLASSPATH=${ORACLE_HOME}/jdbc/lib/ojdbc6.jar:${ORACLE_HOME}/jdbc/lib/ojdbc14.jar:${ORACLE_HOME}/jdbc/lib/nls_charset12.jar; 
CLASSPATH=$CLASSPATH:/export/home/gs806e/tops/jconn2.jar:.;
export CLASSPATH

0

ฉันมีหลายไหในโฟลเดอร์ คำสั่งด้านล่างทำงานให้ฉันในJDK1.8การรวมขวดทั้งหมดที่มีอยู่ในโฟลเดอร์ โปรดทราบว่าการรวมไว้ในเครื่องหมายคำพูดหากคุณมีช่องว่างใน classpath

ของ windows

รวบรวม: javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.java

วิ่ง: java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram

ลินุกซ์

รวบรวม: javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.java

วิ่ง: java -classpath "/home/guestuser/My Jars/sdk/lib/*:/home/guestuser/programs" MyProgram


-1

ฉันพยายามเรียกใช้ไฟล์ Java ไม่ว่าจะเป็น jar หรือเป็นคลาสใน Ubuntu ฉันล้มเหลวในตัวเลือกทั้งสอง ข้อยกเว้นต่อไปนี้คือเอาต์พุต

Download link: https://upload.cat/f694139f88c663b1

java org.statmetrics.Statmetric

หรือ

java -cp /home/elias/statmetrics/statmetrics.jar :. org.statmetrics.Statmetrics

หรือ

java -classpath "/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/*" -jar /home/elias/statmeics/statmetrics.jar org.statmetrics.Statmetrics

Exception in thread "Thread-0" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/adapters/XmlAdapter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at org.statmetrics.c.a(Unknown Source)
    at org.statmetrics.dw.a(Unknown Source)
    at org.statmetrics.dx.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.adapters.XmlAdapter
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    ... 12 more

ฉันพบคำตอบ:

ความโง่เขลาของฉัน

ขั้นตอนแรก: คุณต้องตั้งค่า Java ที่สอดคล้องกัน: ฉันมี Java 11 แต่ฉันตั้งเป็นเส้นทาง Java lib รุ่นที่ 8! - คุณสามารถตั้งค่าเวอร์ชั่น Java ได้จากที่นี่:

  sudo update-alternatives --config java

ขั้นตอนที่ 2: จากนั้นเรียกใช้คำสั่งต่อไปนี้โดยเปลี่ยนพา ธ และชื่อไฟล์เป็นพา ธ และไฟล์ที่เกี่ยวข้อง:

  java -classpath "/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/*" -jar /home/elias/statmetrics/statmetrics.jar org.statmetrics.Statmetrics

มันทำงานสำเร็จแล้ว!

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