I have several class files like such hierarchy directories:
classes
└── com
├── www
│ ├── ant
│ │ └── TAPJUnitResultFormatter.class
│ ├── taglib
│ │ └── IncludeTag.class
│ ├── tomcat
│ ├── util
How could I include them in classpath? I tried to include them one by one, but didn't work.
Thanks.
You might find this helpful
Quoted:
When classes are stored in a directory (folder), like /java/MyClasses/utility/myapp, then the class path
entry points to the directory that contains the first element of the
package name. (in this case, /java/MyClasses, since the package name
is utility.myapp.)
But when classes are stored in an archive file (a .zip or .jar file)
the class path entry is the path to and including the .zip or .jar
file. For example, to use a class library that is in a .jar file, the
command would look something like this:
% java -classpath /java/MyClasses/myclasses.jar utility.myapp.Cool
So basically, point it to the root directory that all your classes exist under. Your "MyClasses" folder is probably named "bin".
Related
I have a .jar that I built following the Oracle docs, using jar cfm hangman.jar Manifest.txt src/classes/app/Main.class. The manifest.txt file contains Main-Class as classes.app.Main, telling where my Main class is. When executed, ClassNotFoundException is thrown, saying it couldn't find classes.app.Main. I need help trying to understand what's wrong here. Is it the main class or maybe a missing classpath?
Here's the project tree:
.
├── hangman.jar
├── Manifest.txt
├── README.md
└── src
├── app
│ ├── Main.java
│ ├── Player.java
│ ├── Players.java
│ ├── Play.java
│ ├── Themes.java
│ ├── Word.java
│ └── Words.java
└── classes
└── app
├── Main.class
├── Play.class
├── Player.class
├── Players.class
├── Themes.class
├── Word.class
└── Words.class
You don't show the code, but it is extremely likely that the package for your class is just app not classes.app, and classes is only a directory name to contain the class files, not actually part of the package hierarchy. The name of a class file entry in a jar, OR the name of a class file relative to a classpath directory, must be exactly a directory path equal to the package hierarchy (if any) plus the class name and the suffix .class, with nothing added or removed. This means your jar should be created by going to the classes directory and then adding the file(s) relative to that directory:
jar cfm hangman.jar Manifest.txt -C classes app/Main.class
and the Main-class entry in the manifest should be app.Main. If you only need main-class in the manifest and nothing else (except version, IIRC), you can have jar create it for you:
jar cfe hangman.jar app.Main -C classes app/Main.class
Also I note that there are other classes in your source tree. If these classes are called or referenced from the Main class, directly or indirectly (i.e. nested), they must also be in the jar. You probably want to use app/* instead, although it is possible you want or even need to be more selective.
Meta: I thought this was covered in the standard tutorial, but although most of the pieces are there they aren't really pulled together anyplace I could find and refer to.
I have created a simple Java9 service example with one service interface and two service implementations and one driver which uses the ServiceLoader. I was able to successfully execute the example with module-path but when I tried to execute the same with java -cp (classpath) I did not get any output, not even any error.
Directory structure
out
├── driver
│ ├── com
│ │ └── company
│ │ └── driver
│ │ └── driver.class
│ └── module-info.class
├── firstServiceImpl
│ ├── com
│ │ └── company
│ │ └── first
│ │ └── serviceImpl
│ │ └── FunImpl1.class
│ └── module-info.class
├── secondServiceImpl
│ ├── com
│ │ └── company
│ │ └── second
│ │ └── serviceImpl
│ │ └── FunImpl2.class
│ └── module-info.class
└── serviceInterface
├── com
│ └── company
│ └── service
│ └── Fun.class
└── module-info.class
command to compile
javac -d out --module-source-path src src/driver/driver.java src/firstServiceImpl/FunImpl1.java src/secondServiceImpl/FunImpl2.java src/serviceInterface/Fun.java
The above command compiles the code with a module-source-path.
command to run
java -cp out/driver:out/serviceInterface/:out/firstServiceImpl/ com.sunil.driver.driver
The above command runs the code with a classpath.
After compiling with module-source-path and run the code with classpath. I do not get any error or output.
Please help me understand why there is no output when run using classpath.
The way service-providers are located depends on if the service-providers are on the classpath or the modulepath. This is described in the documentation of ServiceLoader:
Deploying service providers as modules
A service provider that is developed in a module must be specified in a provides directive in the module declaration. The provides directive specifies both the service and the service provider; this helps to locate the provider when another module, with a uses directive for the service, obtains a service loader for the service. It is strongly recommended that the module does not export the package containing the service provider. There is no support for a module specifying, in a provides directive, a service provider in another module.
[...]
Deploying service providers on the class path
A service provider that is packaged as a JAR file for the class path is identified by placing a provider-configuration file in the resource directory META-INF/services. The name of the provider-configuration file is the fully qualified binary name of the service. The provider-configuration file contains a list of fully qualified binary names of service providers, one per line.
[...]
Basically, if you want to be able to load a service-provider no matter if it's placed on the classpath or modulepath you'll need to specify both a provides directive in the module-info.java file and add the appropriate provider-configuration file under META-INF/services. You also have to make sure you use the correct method for loading the service-providers:
ServiceLoader#load(Class,ClassLoader)
Locates providers in named modules (i.e. modulepath) and unnamed modules (i.e. classpath).
ServiceLoader#load(ModuleLayer,Class)
Only locates providers in named modules (i.e. modulepath).
I am trying to get a better understanding of how the new java module system works, especially when it comes to bundling together java packages to their respective modules.
I could not find a way of asking this question in an easy to understand way without tying it to a specific example.
If I have the following project structure:
.
└── src
└── main
└── java
├── module-info.java
└── org
└── lb
└── app
└── App.java
where module-info.java is:
module lb.module {}
and App.java is:
package org.lb.app;
public class App {
public static void main (String[] args) {
System.out.println("Hello, world!");
}
}
and then I run the command from the . directory:
javac -d build/classes $(find src/main/ -name "*.java")
which gives me the following result:
.
├── build
│ └── classes
│ ├── module-info.class
│ └── org
│ └── lb
│ └── app
│ └── App.class
└── src
└── ...
and finally I run the command:
java --module-path build/classes/ --module lb.module/org.lb.app.App
My questions are:
How does the javac tool knows that module-info.class should be in the root directory folder build/classes if there is no "package information" (e.g. like there are in normal java files), and not, for instance in a folder that mimics the original location (e.g. build/classes/src/main/java/module-info.class
I did not expect it to work, but it does. How does the JVM knows that the org.lb.app package belongs to the lb.module module? I purposefully "misnamed" the module, making it not have same name as the directory that contains it, and also did not export the package. It seems obvious for a human reader, but I want to understand what the java program assumes in order to bundle these two together.
Thank you.
I just spent a little while learning the hard way that Gradle can't make a working jar file if the directory (and thus jar file) is labeled something LIKE_THIS.
Does anyone know why this is? I'm just picking up Java and would like to know why. I've heard it's bad practice to label packages with capital letters as well.
EDIT:
If the directory is all caps, I'd get Error: Could not find or load main class src.main.java.HelloWorld but it would work perfectly fine if it's lableded something like_this.
EDIT:
My directory structure after fixing the label was just from a tutorial, but here it is:
alexanders-mbp:VALID_JAVA alexanderkleinhans$ tree
.
├── build
│ ├── classes
│ │ └── main
│ │ └── net
│ │ └── petrikainulainen
│ │ └── gradle
│ │ └── HelloWorld.class
│ ├── dependency-cache
│ ├── libs
│ │ └── VALID_JAVA.jar
│ └── tmp
│ ├── compileJava
│ └── jar
│ └── MANIFEST.MF
├── build.gradle
└── src
└── main
└── java
└── net
└── petrikainulainen
└── gradle
└── HelloWorld.java
Changing the directory to something_else and re-building makes everything work. BTW, no build errors.
EDIT:
I was following this and couldn't get it to work so I finally cloned the git-repo where I discovered my issue.
To run, I would do
gradle assemble
gradle build
java -jar build/library/VALID_JAVA.jar
(VALID_JAVA being the directory name and thus jar file name.)
It looks like you try to launch src.main.java.HelloWorld, but if you look at the sources from the GIT repository the fully qualified class name is net.petrikainulainen.gradle.HelloWorld (which also matches your directory structure).
To launch the application, use
java -classpath build/libs/VALID_JAVA.jar net.petrikainulainen.gradle.HelloWorld
Note also, according to the decription at the GIT repository, the gradle build creates a runnable jar file which you can launch like
java -jar pathToJarFile
I'm a little bit new with Java, so I apologize in advance. In a Google API Quickstart, a .credentials file is loaded from the method getResourceAsStream and the path as "/client_secret.json". From here, I learned that this getResourceAsStream get's the file from the CLASS path, which confuses me because my src directory structure looks like the following.
.
└── main
├── java
│ └── GmailQuickstart.java
└── resources
└── client_secret.json
When I open a new project (using a servlet) and try to load this, I'm finding this InputStream is null. The src directory of the following project looks like so:
.
└── main
├── java
│ ├── GmailQuickstart.java
│ ├── com
│ │ └── something
│ │ └── HelloWorldServlet.java
│ └── somepackage
│ └── Thing.java
├── resources
│ └── client_sercret.json
└── webapp
└── WEB-INF
└── web.xml
I've tried changing it to what I though would be the same CLASSPATH, but I guess that's not correct. From the previous advice, I've also tried "/main/java/resources/client_secret.json". Obviously I'm not doing something right here.
Could someone help point me in the right direction?
Try to add resources folder to your classpath.
If you are using eclipse, right click your project, configure build path, add your resources folder in Source tab.