Since jars like servlet.jar are usually not downloaded on their own, but rather come part of tomcat/lib folder, should I just add an entry to them in the classpath? Is that the common practice?
I use Ubuntu.
You only need to reference them yourself when you want to compile servlet classes. How to do that depends in turn on the tools used for compilation.
If you're using plain javac, then you could reference them in %CLASSPATH%. But even then, that's considered a poor practice since that would potentially pollute the default classpath of all other Java compilations/applications. Rather write a shell file which sets the classpath right on the current execution environment by utilizing the -cp attribute of javac command.
If you're using a bit decent IDE like Eclipse/Netbeans, then you should just integrate the server in the IDE and associate the project with it. The IDE will then take care about setting the buildpath right. You don't need to set any environment variables then.
You do not need to reference them when you want to run them. The servletcontainer will take care about it by itself.
See also:
How do I import Servlet API in Eclipse?
If you are running a web application on Tomcat then the servlet-api.jar is in the classpath.
Related
My knowledge of ClassLoader in Java at the moment, is a little obscure. That's because I have not found any good documentation geared towards beginner of CLassLoader, thus far. And what I am looking for exactly is in relation to Maven. With disclaimer stated, let me get into my question.
I am writing a Spring MVC application, and I decided to look into how the Dependencies - Jars and classes are loaded using ClassLoader. And what I found is according to the documentation of ClassLoader, classes in Jar are loaded from CLASSPATH, and I can see them under the .m2/repository directory, but CLASSPATH does not yield anything, it's practically empty.
Can somebody please explain to me, how the classes from JAR are loaded into JVM Memory using ClassLoader using Maven, if the CLASSPATH is empty.
Thanks
You're confusing a few things.
The ClassLoader
The ClassLoader is a runtime concept. Maven is a compile time concept. Therefore, one has nothing whatsoever to do with the other. Maven and ClassLoaders do not interact. At all.
When you start a basic java app (java -jar foo.jar or java com.foo.MainClass), you get 2 classloaders. One loader will load system stuff: java.lang.String, for example. the executable itself 'just knows' how to do this (you don't need to configure PATH, CLASSPATH or JAVA_HOME - it just works); up to java 8, it finds rt.jar automatically, which contains String.class and other core classes. Starting from java 11, it finds the jmod files in your java distro.
Then, once the VM has 'booted up', the VM makes another classloader, also based on its built-in stuff: The app classloader.
This one uses 'the classpath'. The source of this depends on how you ran your java app:
java -jar somejar.jar
The source of the classpath in this case is the Class-Path: line in the jar's manifest (the file at META-INF/MANIFEST.MF). And nothing else - the CLASSPATH environment variable, and any -cp or -classpath options are entirely ignored.
java -cp a.jar:b.jar:. com.foo.ClassName
Note that -cp is short for -classpath (they mean the same thing): Here, the classpath is taken to be all the files and directories listed (on windows, use ; as separator instead), and classes are loaded from there. Including com.foo.ClassName itself.
java com.foo.ClassName
If you don't explicitly specify a -cp param, then the environment var CLASSPATH is used. You don't want this though. Always specify classpath.
That's runtime - maven has nothing whatsoever to do with this.
Make your own
You can make your own ClassLoader; the abstraction is such that all it needs to be able to do, is turn a resource name into bytes. That's it. You can make a ClassLoader (literally! public class MyLoader extends java.lang.ClassLoader { ... }) that.. loads data from a network, or generates it on the fly, or fetches it from an encrypted data store. Whatever you like.
Using custom classloaders like this is a solution for finding classes in 'weird' places (not jar files or directories), as well as a mechanism to allow java to 'reload classes' on the fly - very useful when developing, say, web apps, without the use of a hot-code-replacing debugger like eclipse has. ClassLoaders is a mechanism whereby a web server can have the following feature: "I load jars or wars from a certain preconfigured directory.. and if you replace the jar, I will see it and start using the new one".
Writing your own ClassLoader is bordering on rocket science and not usually required unless you're, say, writing an app server. Not a common job.
Maven
To compile source code, the compiler must know the methods and fields and such of all the types you refer. You can't compile "Hello".toLowerCase(); if the compiler doesn't know what String contains.
Thus, compilers also have this notion of 'I need to find classes'. But This is not called class loading, and notably, maven never loads any classes. If it did, any static initializers in any class would run, and mess up your compile. Maven instead just inspects the class file, never letting the VM actually load it, to know what kind of methods and fields and the like are on offer.
java.lang.ClassLoader plays no part in this.
javac itself has a -classpath option as well. So does maven, really.
Maven constructs the classpath automatically, by putting the stuff it already compiled for you (e.g. when compiling the stuff in src/test/java, the compiled stuff from src/main/java is on the classpath), as well as all the dependencies. How? Well, does it matter? Maven does. It constructs a large list of dirs and jars and passes it to javac via the -classpath parameter.
Here are some questions about setting the CLASSPATH in IntelliJ:
Adding Jar files to IntellijIdea classpath
how to add directory to classpath in an application run profile in intellij idea?
Java - setting classpath
Most of the answers involve changing settings in the Project Settings -> Modules -> Sources or -> Dependencies pages. But the word "CLASSPATH" isn't actually on those pages.
For example, the -> Dependencies page lets one explicitly set a place to find other .class files or .jar files. But no "CLASSPATH" anywhere.
Also, setting a location in the -> Sources page seems to indicate what the directory tree for
the .class root should look like, but the actual location is actually set in the Project Settings -> Project -> Project Compiler Output field, again without the word "CLASSPATH".
Is JetBrains trying to hide this word for some reason (eg. it's meant to be a multi-language IDE)? Is there some place to explicitly set the CLASSPATH other than an env variable?
As you say, the CLASSPATH is an environment variable, so it would affect all applications referencing that variable:
The class search path (more commonly known by the shorter name, "class
path") can be set using either the -classpath option when calling a
JDK tool (the preferred method) or by setting the CLASSPATH
environment variable. The -classpath option is preferred because you
can set it individually for each application without affecting other
applications and without other applications modifying its value.
Source: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
You can also use the -classpath option when running your application, which would not affect other Java applications running on your system.
IntelliJ will construct your classpath to include both your application and any dependencies (whether folders or Jars etc.) and passes that to the JVM when you run your application. The IntelliJ GUI does refer to your explicit "Dependencies" and let you edit them. Your application build path would need to contain those dependencies and all of your application code, so it makes sense to include that implicitly.
If you were to use a lot of libraries, your classpath could become very long - having to maintain the list of locations in the class search path manually would be time consuming and (human) error prone - a typo on a folder name and it won't compile / run - so it assumes the task for you.
You'll probably find your IDE passes a number of other arguments to the JVM on your behalf (heap size, GC, JMX extensions and so on) - but that's part of what your IDE is for. Sure, we could invoke things like version control ourselves from the command-line, but why forgo the help? Your IDE isn't trying to "hide" anything from you, it's (hopefully) providing a more intuitive interface for many common development tasks.
CLASSPATH happens to be the name of the environment variable used automatically by Java.
It's generally considered a better option to use the -cp argument to explicitly set the classpath rather than fighting with CLASSPATH conflicts since it's process-wide.
It's not trying to "hide" it at all; there's just no reason to use it.
I would like to use the library "Lucene" with java. The instructions to use it tell me I have to put the jar's cointaining the classes inside the CLASSPATH.
The CLASSPATH is the directory containing all the default classes of Java? Or the directory of my specific project? I'm using Eclipse as IDE.
Really confused about that! Thank you.
USEFUL SOLUTION: http://www.avajava.com/tutorials/lessons/how-do-i-use-lucene-to-index-and-search-text-files.html
The Classpath is a collection of directories and JAR files inside which the Java runtime will look for classes.
It can be configured via an environment variable named CLASSPATH, but this usage is not recommended, as it tends to constantly result in problems.
The preferred way to configure the classpath when running a Java program is to pass it via the -cp command line switch when you start the Java interpreter. Usually you write a shell script so you don't have to type it out every time.
If your issue is with using the classes inside the IDE where you write your code, then it depends of course on the IDE. For eclipse, the "Java Build Path" tab of the project properties is where you configure the classpath.
Can I modify src.zip(it contains java classes predefined ) so that i
first unzip and then add my personal package and zip and replace the src.zip with this
new src.zip i modified.
so that i can import them just like any other classes.
Check out the Java tutorial on the CLASSPATH. That provides an extensible means of adding libraries for Java usage which doesn't impact the original install, and can be segregated between running processes.
The CLASSPATH variable is one way to tell applications, including the
JDK tools, where to look for user classes. (Classes that are part of
the JRE, JDK platform, and extensions should be defined through other
means, such as the bootstrap class path or the extensions directory.)
The preferred way to specify the class path is by using the -cp
command line switch. This allows the CLASSPATH to be set individually
for each application without affecting other applications
You'll rarely have to touch the JDK/JRE install, and I would strongly recommend against it. By using mechanisms such as the above, each app can specify its own libs, and you can swap between variants of the JDK/JRE without having to ensure each deployment is modified.
The src.zip contains the source files not the class files and it won't be part of the built in classpath either.
If you have to import your classes, you have to keep you other dependent jars in the classpath.
What you want is set the classpath.
Of cause, you can add your classes to the rt.jar file, but I highly recommend not to do so.
How to set the classpath
src.zip folder will not be included in java classpath, yes you can add your own classes in it. But in order to add it your classpath ,it needs to be compiled and the resulting class files you can add use.
But its not recommended to modify jdk source, unless you know exactly what you are trying to do.
I just asked a recent question about distributing executable JARs and their dependencies, and it made me realize that my understanding of JARs may be fundamentally flawed.
Thus, some might say "Hey now! This here is a duplicate question!" But I say nay, this question is a completely separate offshoot of this
original question, and is concerned with Java fundamentals!
If I have an application that depends on, say, the Apache Commons CLI as well as JODA Time, and I pack this app up into a distributable JAR, my original question was: Without including the CLI and JODA JARs in my JAR, how does the program run on the client-side???
I am now thinking that since my code, which uses CLI and JODA, gets compiled into classfiles, and that bytecode is what gets packaged, then there is no need to include CLI or JODA (or any other 3rd party JAR) in my JAR, since it is all now functioning bytecode.
Can someone confirm or correct me? This revelation, though late in coming, has been staggering.
No, that is not quite right. The key to everything is the classpath. Is all of the compiled code and/or other resources on the classpath? If you package everything up in one single jar, then yes, it is in the classpath and the JVM will locate all the resources to run. Otherwise, you need to specify (with a .bat or .sh file or something) all the resources that your application is dependent on, so the JVM will be able to appropriately look for those resources (be they Java code or properties files or whatever).
Also if I am reading your question right, are you assuming that the CLI and JODA code gets compiled into your code? If so, I hate to burst your bubble, but that is not the case. When your code compiles, it does not bring in dependencies (not in the sense you may be thinking). What it does at a conceptual level (correct me if I'm wrong JVM gurus) is it references other classes. Those references are what you are building when you code a class and compile it. At runtime the JVM will attempt to locate the compiled class behind the reference and THAT is where you either need the jar with those classes in the classpath OR you need those classes in your executable jar.
Make sense?
The third party libraries (JodaTime, for example) need to be on the classpath during runtime. Not "packaged within your JAR".
If your app is launched from a JAR. You should specify the classpath in the manifest file which is packaged within the jar - http://download.oracle.com/javase/tutorial/deployment/jar/downman.html
You can have ANT generate the manifest classpath for you using the manifestclasspath element - http://ant.apache.org/manual/Tasks/manifestclasspath.html