Is it true that the rmi interface compiler is not needed for java 1.5 or newer and that just compiling the java file where the UnicastRemoteObject is defined with javac is enough?Rmic still works and it generates a stub class file if you give it the class file of the implementation of the remote object.
According to the RMI tutorial:
http://download.oracle.com/javase/tutorial/rmi/overview.html
Compiling Sources
As with any Java program, you use the
javac compiler to compile the source
files. The source files contain the
declarations of the remote interfaces,
their implementations, any other
server classes, and the client
classes. Note: With versions prior to
Java Platform, Standard Edition 5.0,
an additional step was required to
build stub classes, by using the rmic
compiler. However, this step is no
longer necessary.
See the preamble to the Javadoc for UnicastRemoteObiect. You can avoid using rmic under specific circumstances, i.e. when you construct or export the remote object providing a port number parameter (even zero), for reasons described in the documentation.
Related
I am having a doubt.
My understanding is that jdk has [ jre + development tools (Java, javac, debugger etc.) + source code (src.zip) ].
Now working of java compiler is nothing to do with the running of class file.
If I am compiling a .java file then from where the java compiler is importing the package?
I could find the packages under jre.
If I do not opt to install jre while installing jdk, does that mean I will not be able to compile the java file having import statement?
Please help.
First, as a minor remark, a statement like
import java.util.List;
just introduces an abbreviation, allowing you to use the simple word List later in your code instead of the full class name java.util.List. So it's not so much the import statement itself, but the usage of a class like java.util.List that needs some explanation.
You understand correctly that, to compile your java file, the compiler needs some information about every class you use, and it typically finds this information in some jar file containing that class.
Now, where is this jar file containing the java.util.List class that the compiler reads? You're correct, it comes from the JRE, from the rt.jar that's part of the system classpath (the Java compiler itself is a java program that needs the basic classes itself, so wherever you successfully run javac, you always have an rt.jar available).
If your source code used a class from some other library, you'd have to specify that library on the javac command line, using an option like -cp.
Jdk = JRE + other tools like you mentioned.
When you are compiling your java file and you are using java inbuild library then it uses rt.jar to resolve dependency i.e import statements.
You can refer below link for the difference
What is the difference between JVM, JDK, JRE & OpenJDK?
The class BasicLabelUI in javax/swing/plaf/basic is affected by a confirmed bug.
In my application I need functionality provided by the fixed version (filed for v9).
Due to both legal and technical reasons, I'm still bound to the affected JDK version.
My approach was to create a package javax/swing/plaf/basic inside my project, containing the fixed version.
How can I force my project to favor my included version of the class over the defective class in the installed JDK?
This has to be somewhat portable as the fixed class also has to be working on customer side and the defective class in the JDK installation has to be disregarded. Therefore, I dont want to modify the JDK, but rather bypass this particular class.
As mentioned by the other answers, you could in theory of course unzip your JVM's rt.jar file and replace the file with a compatible bugfixed version.
Any classes of the Java Class library such as those of Swing are loaded by the bootstrap class loader which looks up its classes from this rt.jar. You can generally not prepend classes to this classpath without adding them to this file. There is a (non-standard) VM option
-Xbootclasspath/jarWithPatchedClass.jar:path
where you would prepend a jar file that includes the patched version, but this does not necessarily work on any Java virtual machine. Also, it is illegal to deploy an application that changes this hehavior! As it is stated in the official documentation:
Do not deploy applications that use this option to override a class in
rt.jar because this violates the Java Runtime Environment binary code
license.
If you however appended a class to the bootstrap class loader (what is possible without using non-standard APIs by using the instrumentation API), the runtime would still load the original class as the bootstrap class loader in this case searches the rt.jar first. It is therefore impossible to "shadow" the broken class without modifying this file.
Finally, it is always illegal to distribute a VM with a patched file, i.e. putting it into a production system for a customer. The license agreement states clearly that you need to
[...] distribute the [Java runtime] complete and unmodified and only bundled as part of your applets and applications
Changing the VM that you distribute is therefore not recommended as you might face legal consequences when this is ever uncovered.
Of course, you can in theory build your own version of the OpenJDK but you could not call the binary Java anymore when you distribute it and I assume that your customer would not allow for this by what you suggest in your answer. By experience, many secure environments compute hashes of binaries before execution what would prohibit both approaches of tweaking the executing VM.
The easiest solution for you would probably be the creation of a Java agent that you you add to your VM process on startup. In the end, this is very similar to adding a library as a class path dependency:
java -javaagent:bugFixAgent.jar -jar myApp.jar
A Java agent is capable of replacing a class's binary representation when the application is started and can therefore change the implementation of the buggy method.
In your case, an agent would look something like the following where you need to include the patched class file as a ressource:
public static class BugFixAgent {
public static void premain(String args, Instrumentation inst) {
inst.addClassFileTransformer(new ClassFileTransformer() {
#Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if (className.equals("javax/swing/plaf/basic/BasicLabelUI")) {
return patchedClassFile; // as found in the repository
// Consider removing the transformer for future class loading
} else {
return null; // skips instrumentation for other classes
}
}
});
}
}
The javadoc java.lang.instrumentation package offers a detail description of how to build and implement a Java agent. Using this approach, you can use the fixed version of the class in question without breaking the license agreement.
From experience, Java agents are a great way for fixing temporary bugs in third party libraries and in the Java Class Library without needing to deploy changes in your code or even being required to deploy a new version for a customer. As a matter of fact, this is a typical use case for using a Java agent.
How can I force my project to favor my included version of the class over the defective class in the installed JDK?
Simple answer - you can't. At least, not while strictly obeying the constraint that you should use the affected Java version.
Assuming that you can identify an appropriate version in the OpenJDK source repos, it would be possible to build your own flavor of the Java libraries with a bug patched. However, that won't be real Java. Certainly, it won't qualify as "the affected Java version" that you are constrained to use. (And besides, you are committing yourself to an endless cycle of reapplying your patch to each new patch release of the current version of Java ...)
It is also possible in theory to put a modified version of some Java standard library class into a JAR and prepend it to the JVM's bootstrap classpath using the -Xbootclasspath command line option. But that is tantamount to changing "the affected Java version" too.
Doing it by using a Java agent to use a patched version of the class is breaking the rules too. And it is more complicated. (If you are going to break your rules, do it the easy way ...)
If you and your customers do decide that tweaking the JVM is an acceptable solution, then doing it via the bootstrap classpath is probably the simplest and cleanest approach. And it is DEFINITELY legal1.
However, I'd recommend that you find a workaround for the bug until a version of Java 9 with your fix is released.
1 - Actually, even the build-from-modified-source approach is legal, because the Oracle Binary license does not apply to that. The Binary license is about distributing a modified version of an Oracle binary. The other possible issue is that you may be violating the terms for using the Java trademark(s) if you distribute a version that is incompatible with "true" Java, and call your distro "Java". The solution to that is ... don't call it "Java"!
However, don't just follow my advice. Ask a lawyer. Better yet, don't do it at all. It is unnecessarily complicated.
I have an application using Jython 2.1.
In the app I was using jythonc to convert the python scripts to java classes and then include these classes in my webapp like any other.
So I was able to assign package name to python scripts and access these classes like any other java class.
Now I plan to migrate to Jython 2.5. Jython 2.5 has removed support for jythonc.
So I tried to use
jython -m compileall /path/to/my/python/scripts.
When I do that I get all the compiled bytecode files in the same folder. Each of the files have names like myclass$py.class (where my python file is myclass.py).
My questions -
First of all can I access these classes in another normal java
class?
If so, what is the class name I should use ? When I use it like new
myclass() my code does not compile.
Is there a way, I can assign / force a package name or class name
for the generated bytecode with compileall?
Note -
I need to upgrade to jython 2.5 because I need newer versions of
python that it supports.
I would like to stick with pre-compiling the
python code into bytecode, as I want to do optimizations on the
bytecode. So the recommended object factory method is only a
last resort. I am assuming the object factory approach will not allow
me to process the generated bytecode.
Any help is appreciated.
Eclipse is adding #Override annotations when I implement methods of an interface. Eclipse seems to have no problem with this. And our automated build process from Cruise Control seems to have no problem with this. But when I build from the command-line, with ant running javac, I get this error:
[javac] C:\path\project\src\com\us\MyClass.java:70: method does not override a method from its superclass
[javac] #Override
[javac] ^
[javac] 1 error
Eclipse is running under Java 1.6. Cruise Control is running Java 1.5. My ant build fails regardless of which version of Java I use.
The #Override annotation spec changed in Java 1.6. In Java 1.5, the compiler did not allow the #Override annotation on implemented interface methods, but in 1.6 it does. First search result I found is a blog post here.. It was not well documented, but it did change.
Eclipse is adding it because your Eclipse is set for 1.6 compliance. You should try to keep your build and eclipse environments on the same version of Java. It's unclear to me by your specifying Cruise Control is running Java 5 on whether or not it is compiling using a separate JDK6 or not.
Separate from the above 1.5 vs 1.6 #Override annotation rules, remember that Eclipse has its own compiler implementation (not javac) and will occasionally have different behavior. Whenever something compiles in Eclipse, but not Ant or Maven, you will need to find a way to make both compilers happy.
I can't really explain the problem you're seeing but it seems to be related to the fact that JDK 5 will not allow #Override on implemented methods of an interface, only on overridden methods present in a super class.
JDK 6 will allow #Override on any of them.
If your ant build fails it may be passing a source parameter to javac, asking for JDK 5 compliance.
The direct answer to the question "Why" an error is raised by javac when #Override is used in the context of a method implementation is actually in the java specifications:
"The rationale for this is that a concrete class that implements an interface will necessarily override all the interface's methods irrespective of the #Override annotation, and so it would be confusing to have the semantics of this annotation interact with the rules for implementing interfaces."
See http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.6.1.4
But apparently someone changed his mind for java 1.6 and 1.5 u21...
#Override tags for implemented methods are new to Java 1.6. In Java 1.5 #Override is only correct when overriding a method in a base class. Read more here and here.
A lot of people, including me, got busted by this. See here for a bigger SO discussion
Eclipse would be pointing to 1.6 version of Java rather than 1.5.
See here for configuring java version in eclipse.
Ensure that there is only one definition of that interface.
Example:
HttpServletRequest
This is an interface with different specs depending on provider.
Compare pax-web-jetty and apache-felix-jetty. They have different methods.
I have had the same problem when building a project with ANT. The solution to the problem was to change the following property inside the build.properties file:
javac.compiler=org.eclipse.jdt.core.JDTCompilerAdapter
to:
javac.compiler=modern
That solved the problem and the project got compiled and deployed successfully.
I have a java program that I'm required to compile into a Linux native program using gcj-4.3. This program requires serial port access. The javax.comm api provides serial port access but I'm not sure how to get my compiled java program to use it.
The target box has Java installed, but of course my compiled program isn't running in the JRE...so I'm not exactly sure how I can link in the comm.jar file or how that file can find the .properties file it requires.
I wonder if I can just compile the comm.jar allong with my .jar file and link the two object files together. Can my code then reference the classes in comm.jar?
Thanks in advance for your help!
I'm not an GCJ expert but I have some suggestions (I'm not providing the syntax, this will require some exploration that I didn't perform):
first, I think that you'll have to compile comm.jar into a (shared) library,
then, you'll have to link your code against the library,
finally, use the GCJ_PROPERTIES environment variable to pass properties to the program at invocation time.
The following pointers might be helpful to implement this:
GCJ---The GNU Compiler for Java (great resources IMO, covers all the steps mentioned above)
GCJ – Getting Started (more an intro but still nice)
Compile ActiveMQ with GCJ (more use cases but I don't think they apply here)
And of course, the official documentation :)