-classpath option for javac and java - java

I'm confused with the role -classpath option plays in both compiling and running a java program. Please help me understand.

Because they are two separate operations and not necessarily the same paths.
The runtime dependencies are often more extensive than the compile time dependencies. For example, many programs will code to interfaces, which limits the compile time dependencies to those interfaces. At runtime, the VM must be able to resolve the implementations of those interfaces, which are not required until they are loaded at runtime.

it simply in both cases tells javac and java where to find dependencies required for your program to both compile and run

The reason it is done twice is that the environment you compile the code in may not be the same environment you run the code in.

Java loads classes at runtime. For example, you could write a method that forces loading of class X, compile it, write class X, compile it, and then run them together. In addition, you typically refer to classes by a fully specified name, but could run the same program with different versions of that class (e.g., a different version of the library). Thus, you need to tell Java where it could potentially find the classes that it needs to load.
As for compilation, to ensure type safety, you have to provide the Java compiler at least with the interfaces or base classes that you are referring to and making calls on, so that the compiler can at least ensure that the call would be legal. For that reason, you have to tell it where to find the jars containing them.
Here is an example. Let's say you want to use JMS (a messaging framework) in a core Java program. At compile time, you need to at least tell javac where to find the JMS interfaces. At runtime, you need to provide these interfaces, but you also need to provide the JAR with the actual implementation (e.g., ActiveMQ).

In C++ I believe it is the case that linking happens around compile-time, to create an executable (I am not a C++ programmer so I'm not sure about that).
In Java, the linker step happens at runtime (see the JVM spec, "Loading, Linking and Initalizing"). From your question it sounds like you understand why the classpath needs to be specified at compile time (because you might reference classes from third-party JARs in your code), so I will just explain that when your program is being run, those classes are not loaded into the JVM until they are referenced. At this point, the JVM needs to know where to find their representation.

The compiler has to know where to look to satisfy compile-time dependencies.
The VM has to know where to look to satisfy runtime dependencies.

At compile time, you need to tell javac where to find third-party and user-defined classes. At runtime, you also need to tell java where to find third-party and user-defined classes. In both cases, one way to change the class path is to use the JDK Tools' -classpath option. Checkout the Setting the Class Path technical note for more details.

Related

Can I force GWT compilation without entry point? (To validate compatibility to GWT)

This question is related to, but not a duplicate of, this question.
My issue is slightly different; I have a "utility module", shared between the client and server code, and it contains no GWT-specific code.
I understand that normally, all the sources are pulled into one specific project, where everything is compiled together. But there is one issue with that: I only get to know if my utility project is "GWT compatible", when I compile the main project. This is way too late; I haven't even got around to start on the main project, but I want to know before I make a "commit" to my SCM, that my utility project is "GWT compatible".
In other words, I want to validate the utility project for GWT compatibility, independently from it's use in a separate project (module).
There's a large part of the JRE that is not covered by GWT, and it is particularly likely in a utility module that non-GWT-compatible classes or method be used. That is what I want to validate against.
EDIT: I could add a "dummy entry point", I suppose, but that makes the project depend on GWT, which I don't want to, since it is "general" code, also to be used by people that don't use GWT. If it matters, I use Maven as build system.
EDIT2: No matter what I do, I will only get real compilation/validation with an entry point (does NOT need to reference any of the classes). Neither <force>true</force>, nor <failOnError>true</failOnError> will do. Is there a way I can define that entry point, for the shared project, such that only gwt-maven-plugin sees it, but not javac (so as not to add an unneeded dependency in the Java code)?
The compiler actually always visits all code on the source path (note: not quite the same as the classpath), by starting at the requested module with any <source> tags, and then checking each <inherits> along the way. If it finds something that isn't compatible or isn't compilable, it will mark it as broken, and move on - as long as nothing actually depends on it (i.e. an EntryPoint, or something that an EntryPoint depends on) you'll just see this message:
Validating newly compiled units
Ignored 1 unit with compilation errors in first pass.
Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
If you include that -strict flag, the compile will actually fail when it hits something that can't be included correctly.
This work is done in the very early stages of the compile, while constructing the TypeOracle, which is used for Generators, long before any JS is built. That type oracle is passed to generators, which need to be able to ask questions like 'what interfaces on the sourcepath have a JSO implementation' and 'what are all possible subclasses of List'. Generators can do a huge number of things, including emit even more types which then need to be parsed, compiled, and the process continues until a full JProgram is created of all possible types, based on the current set of modules.
That JProgram then gets compiled down based on what can be reached from the roots - the entrypoint, as well as a few other details such as how to emulate Java details like casts, arrays, longs, exceptions, etc.
If -strict was not specified, and the compiler ends up needing to reach something which is unavailable due to earlier compilation problems, that is the time you find out. Using -strict to stop earlier will help ensure that you catch those issues sooner.
One more fun fact: By default, with com.google.gwt.user.User in your module (or any other <inherits> that depends on it), you already have an entrypoint, or several! These do some quick checking that your page is working correctly, such as using a strict doctype, or the browser actually matching the expected user.agent setting. This means that it is usually possible to compile a module even without an entrypoint (except with gwt-maven-plugin:compile, which will not consider a module for compilation just by those built-in ones).
EDIT: Okay, even one more: From http://www.gwtproject.org/doc/latest/DevGuideCompilingAndDebugging.html, combined with -strict, it looks like you can force the validation to run without actually compiling to JS:
-validateOnly Validate all source code, but do not compile
I don't think it's possible because the GWT compiler does not compile any unused code.
This means that your shared utility "module" may have code in it that is not compatible with GWT, but it will not cause any problems as long as GWT code never calls such incompatible classes or methods. Without an entry point GWT compiler won't know which code is used and which is not - it will assume that all of it is unused.

Class Loading: Compile time or Runtime

Is java class loaded at compile time or Runtime? I know you can dynamically load a java class using your own Class Loaders or calling Class.forName("fully qualified name of java file").
But if I am not using any of the above techniques then does it means that Java classes are loaded at compile time?
No. The JLS explains how loading and linking is runtime. Any binary-compatible revision of a class can be thrown in place of an existing class.
A class is compiled with a symbolic reference to other classes, not the code of those classes.
However with certain non-JVM compilers like GCJ classes can be compiled ahead of time into one executable.
Classes are loaded at runtime to execute their code.
Classes are loaded at compile time to check code using the class for type safety.
Whenever you write code that uses a class (eg, calling a method on it), the compiler needs to load that class to make sense of your code (eg, to check methods or base type)
At compile time nothing is loaded. At compile time classes are just generated from sources.
The difference could be if a class is loaded by the ClassLoader when the JVM powers up or if you do it dynamically during the execution, but they are two sides of the same medal.
In both cases they are loaded dynamically, but in the former this is done as soon as the JVM starts.
As many others have stated, classes are loaded at runtime unless you are using an AOT compiler to allow them to run in non-JVM environments. If you want to read up all the details on how the Java Virtual Machine starts up, initializes and loads the first then subsequent classes you can take a look at the Java SE 7 specifications.

Java: Compile inter-related classes

Say I have: class A depends on class B depends on class C depends on class A.
It seems impossible to compile. I have read this post about disabling compile-time depedency-checking, but all my classes are within the classpath, well-defined, etc. The only problem is that they mutually depend on each other.
Is there a way to write such an application that would compile without a hitch?
We do have several such dependency cycles in our legacy codebase and they do compile without a hitch.
This is not to say it is good to have cyclic dependencies - on the contrary. I intend to get rid of them eventually to clean up our architecture. Nevertheless, in the meantime, the code still compiles and works.
The important thing here is that the compiler must be able to compile all the classes at the same time. If this is the case, there should be no problem. Of course, you should take care of the usual directory layout problems.
If the packages can't be compiled together, it gets more complicated - you might have to create dummy implementations first (which don't depend on the other classes) and then (when you have the right classes) substitute them. But I can't really imagine an reason for not being able to compile them together.
You can have this circular dependancy like this as Java knows which files to read to find the code from the name. i.e. it compiles them all at once. You will only have a problem if you try to compile one at a time.

What's the difference of compile time libraries and run time libraries in java?

And what are the pro's con's of using either?
I actually saw it in Netbeans under Project Properties > Libraries for Java Applications. We have two tabs, one for compile time libraries and run time libraries, and it looks like we can add a library to either independent of each other
There is no such a thing as compile time libraries vs. runtime libraries
Perhaps you're mixing some concepts.
In Java the libraries to be used are statically validated at compile time and also validated at runtime.
For instance if you want to use IterableMap specified in the Apache Collections library. The compiler validates "at compile time" you are invoking a method that exist in that class.
But the compiler doesn't link or do much of anything with that library, you still need it at runtime. So, when your code executes, the Java runtime, searches for that class again, and invokes the method the compiler verified existed.
And that what there is.
The UI and terminology of the Libraries properties dialog is pretty confusing.
The Help button on that dialog will give you a fair bit of info.
The Compile-time library list may be a subset of the Run-time library list.
Consider this situation...
You have source code that imports classes from on a library 'widgets.jar'. The class files in widgets.jar reference symbols from the jar file 'xml.jar'. If your source code does not import classes from xml.jar, you could define the Compile-time libraries list to contain just widgets.jar.
When you try to run your project, you will probably need to include xml.jar in the Run-time libraries list to prevent ClassNotFoundException's.
Perhaps, this comes into play when you want to load a library dynamically, or check for an existence of the library and then execute the code.
During compilation, compiler needs to know what the signatures of the methods, classes etc to know if you code is correct. Hence you add the compile time library.
During runtime, JVM still needs the library to run that specific code. But you can put a logic to avoid that code by checking if the library exists, for example by doing Class.for() method. Some libraries might already exist in the system (qt.jar for example) or might not, and you can check and execute your code accordingly.
Please correct me if I am wrong.
As others have stated, you are confusing concepts. I think what you are really trying to understand is what Maven refers to as dependency scope. Sometimes you only need a dependency at compile time because you expect it to be provided at runtime, and sometimes you need it at runtime but not compile time.

Use a custom classloader at compile time

Is it possible to specify a custom classloader for javac (or some alternative java compiler)?
I'd love such a feat because it would allow me to compile classes that use classes that are only found by my special classloader.
For the curious ones: I'd write a classloder that connects to a database and creates classes based on the tables it finds.
When you run javac you can specify the classloader like so:
javac -J-Djava.system.class.loader=org.awesome.classloader sourcefile.java
It may be possible to initialize a custom classloader and then use it while calling the new Java 6 Compiler API in javax.tools.
The only two ways I know of plugging directly into javac (as run on the command line) are via the annotation processor or via a compiler-specific hack.
Just to expand on Michael's answer, if you cannot use Java6, look at the sun. packages--they have always been available to java apps and have always had a compiler in there, it's just not standard Java so you don't hear about it much and the API is subject to change (like moving it to the javax.tools package!)
Take a look at ClassLoader.defineClass. I used it myself for loading plugins into a program I created, in which I loaded a file's bytes into a new class.
If the classes all conform to the same Interface you could just provide that at compile time..
If not then I don't see what you are gaining by not outputing .java files based on the DB and compiling that.

Categories