I just built Tomcat7, and used file command to check the generated class files, it prints as below
output/classes/org/apache/coyote/AbstractProcessor$1.class: compiled Java class data, version 52.0 [64-bit architecture=65593] [architecture=6382440]
output/classes/org/apache/coyote/AbstractProcessor.class: compiled Java class data, version 52.0 [architecture=14878464] [architecture=56073]
What does the architecture means in the output? Why compiler generates differently for the classes from a same file?
And why did the compiler generate AbstractProcessor$1.class for https://github.com/apache/tomcat/blob/7.0.x/java/org/apache/coyote/AbstractProcessor.java? There is no anonymous inner class in source code.
It looks like this is actually a bug in the file command. Looking at the file cafebabe in the file github mirror, which handles detecting both Java class files and Mach-O (i.e. Mac) binaries (because they both use the same magic strings), it seems that the "architecture" part is meant to only be used for the latter, but somehow gets applied to your class files.
Feel free to ignore that.
Regarding the $1 file, looking at it with javap shows that it is a synthetic class and contains a method named $SwitchMap$org$apache$tomcat$util$log$UserDataHelper$Mode (sic), suggesting that it is generated by the compiler to help with the switch statement in the code:
$ javap AbstractProcessor\$1.class
Compiled from "AbstractProcessor.java"
class org.apache.coyote.AbstractProcessor$1 {
static final int[] $SwitchMap$org$apache$tomcat$util$log$UserDataHelper$Mode;
static {};
}
Related
I have a pile of .java files. They all have the same class name public MyClass. They all have a main method. They all may or may not have a package declaration at top, and I do not know ahead of time.
I am trying to write a script to compile and run these java programs. This is easy for the files without the package declaration... I just do some cp operations to setup, javac MyClass.java and java MyClass, then rm to teardown. However, the files with the package declaration require special attention. I have a few options that occur to me, including deleting the package lines, or attempting to read the package lines so that I know what the resulting directory structure should be. Both of these require me to go parsing through the .java files, which makes me sad.
Is there a way to compile and run these files without having to parse the .java files? Something like:
javac --ignore_package_structure MyClass.java
would be ideal, but a quick look at the javac man pages suggests that such a thing doesn't exist.
If we can assume that each student submits a single source file named HelloWorld.java, then we can use the "Launch Single-File Source-Code Programs" feature added by JEP 330 in Java 11:
java HelloWorld.java
We don't run javac first, we don't get a .class file (no cleanup needed), and any package declaration is handled automatically.
Remember, the students are still allowed to use many classes, they just all have to be submitted to you in a single source file.
The name of the class doesn't even matter. The first class in the source file is executed.
There isn't any easy way to do this. You could use regex though, and replace all imports with this simple java regex:
"package \w+;"g
Simply stated, you create a Java program to replace all the package names.
How to replace files: Find and replace words/lines in a file
I was inspecting the class file format since I wanted to add source code to the class file (which was possible in early Java versions) but all I found was a SourceFile attribute and the SourceDebug attribute. I was looking for the complete source code of the class to be bundled with the class file to ease the post-processing pipeline.
Does anyone know if my memories are wrong or how I can bundle the complete source code of a class within the class file so that I do not have to look up for the java-file when I want to check the source code?
Is there a compiler switch to do that?
Javac has a -g option adding additional debug information. Can someone tell me whats are the information it adds? Without the -g switch it generates lines of code index and source file information.
The main problem I have is generate a class file but only have a reference to a source file that might change. I want simply to bundle up source and class file.
In maven I can simply copy over all the source files to the target directory but would might be incompatible with Eclipse, IntelliJ and NetBeans IDE (and what not)... .
Using a decompiler will also provide a way to extract a useful representation of the source code since most decompiler will value the lines of code information and position the decompiled structures accordingly within the source code.
Since some scenarios will require access to comments and a correct representation on a char by char level, the decompiler would be a second rate solution.
One possible solution I found is defining a new class-file attribute (which is legal) that contains the source. Since the source is huge when compared to the class file, the content might be best compressed (yielding a 1:5 to 1:10 ratio).
This way the class file and the sources stay bundled.
The JVM specification guarantees that every JVM/Tool has to ignore unknown attributes.
I will invest into a wrapper of javac application, that ensures the source was not modified during compilation (and if yes, redo the compilation process) and after compilation is done adding the source code as a class-file attribute.
Since this will be incompatible to the IDE-build cycle of Eclipse (and most likely IntelliJ and NetBeans) it will also require a special post processor.
So integration will also require alternatives to the JavaBuilder.
Once the source code is attached to the class file in question it is very easy to do a lot of advanced stuff with it that helps with both maintaining and managing code. For me its important that the source code and a class stay together and the source information is a 100% percent equal to the source code it was compiled from.
I am a little bit confused...
I know that classes are loaded by the class loader only when they are needed,that is when we are trying to use static variables or when we are creating instance of that class.Thus if we have for e.g. 3 classes in our program and we are going to use only one,then only that particular class will be loaded and rest are not,but when we run the java compiler,it will create 3 .class files,I know these 3 .class files are byte code files,but then what is this byte code and what is the difference between loading a class and generating bytecode of a class?Where is the use of this byte code?If we are not going to use a particular class,then what is the need of generating a bytecode for that class?
Java is a compiled language. The purpose of compiling into bytecode is to allow the code to run on the JVM on any platform. Platform independence is a feature built into java.
Furthermore, you don't have to compile all three class files unless they have inter-dependencies. You can specify which specific files to compile in the console javac command. If you are using an IDE, check your settings or exclude the undesired class from the project.
Loading a class happens at runtime, when you're preparing to invoke whatever properties the class has.
Generating the bytecode of a class happens at compile time. This allows the code to be run on the virtual machine.
Java is a compiled language, and it runs on top of the Java Virtual Machine. Compiling bytecode translates whatever higher level code (be it Java, Scala, or Clojure) into machine-independent instructions to be read by the JVM. This is why that your (backend-specific) program will generally run without modification on Linux, Windows, and Mac OS X.
The Java language will compile any classes that have dependencies on each other within the path, so if you have a class but it is not used, chances are it will not be compiled. There may be tools that override that, so if you find yourself not using a class, then remove the class so that unnecessary bytecode is not generated.
Difference between languages like C++ and java is byte code. C++ binaries(compiled,assembled,linked) will have the machine(op) codes for the OS it got compiled for. In the case of java the byte code is the target for JVM. Byte code will have the opcodes for JVM. JVM in turn will initiate the respective os calls. So bytecode and JVM makes java programs independent of os.
Reg loading class loading,it happens when the program needs it. This is at runtime. JIT will do the second compilation of class when needed.
When we compile .java we get .class file.
The .class file is called byte code.
The Byte code in Java is nothing but a .class file which is not understandable by humans i.e (00110011). These .class files are generated only after the compilation of .java.
These .class file can be used to run on any platform.
Why don't we give the filename.class file after java command, instead of only filename?
Suppose we want to compile the test.java program, then we run javac test.java. It is ok!
After that it will produce test.class file but to run the program we run java test instead of java test.class. What is the reason for this?
Because you are not describing a file to run. You are telling Java which class contains the main method - and the class' name is (in your case) filename, not filename.class.
The fact that the bytecode is almost always contained in files on the filesystem is an implementation detail. The classpath you pass to the java command tells it where to look for classes, and then the main class argument tells it which class to use.
(It's different for javac, because this program specifically does take source files and compiles them into bytecode.)
You don't pass a file name to the java command either. You pass it a fully qualified class name. Something like com.yourcompany.yourapp.Main. Java then finds the .class file for this class name, by looking into all the directories and jar files in the classpath.
It's an implementation detail. The Java class loader system can extended by custom code to make it behave differently. For example, some companies have written encrypted class loaders that are capable of decrypting and loading encrypted class files on the fly. You could hypothetically create a similar system that bundles a bunch of classes together into something resembling a .NET assembly instead of a Jar file (which is really just a zip file).
when you execute "java test.class"
You get either
Could not find or load main class test.class
or
Exception in thread "main" java.lang.NoClassDefFoundError: test/class
This is because "java" in "java test.class" is jvm. It looks for main method in class called "class" instead of "test". Dot in "java test.class" has a significant meaning. So how jvm looks at "java test.class", in a package called "test" it looks for a java class named "class".
*test.class*
*test* - package name
*class* - java filename
Hope this helps !!
Just to summarise everything to the details,
when one does
java filename.java
s/he actually runs the java compiler and converts the code to instructions that a JVM understands.
Now when one runs
javac main_file
s/he invokes the JVM to run the entire project whose main method is found in the class main_file
This main_file is actually the fully qualified name of the class i.e. if I have a project ProjectX and this main class is in package src.java.hello.main,
You should run the command
java src.java.hello.main.main_file
Hence this . is actually a reserved thing at JVM end and we cannot give .class as part of the argument to the java command.
The Javac compiler creates file called Xyz.class (Here Xyz is FileName)
that contains the byte version of the program
Java Bytecode is nothing but intermediate Representation of Your Program that contains instruction the Java interpreter will execute.
thus, the output of javac is not code that can be directly executed
in short, javac keyword is used for the Compile the Java program
if we Use .class with javac (Already compiled File .class File) then How can compile already compile file
so Valid Syntax is:
Javac Xyz.java (Compile the Java Program)
java Xyz (Run the Java Program)
Suppose there is a simple java program:
package pkg;
import java.lang.System;
public class A {
public static void main(String[] args){
System.out.println("\nhello, world\n good");
System.out.println(args.length);
}
}
After compilation, I get A.class, the bytecode file. I want to know whether A.class contains the library function println? I know for sure in C++/C the EXE will contain library functions (not the DLL version).
A derived question is how the JVM get function println? Is it a dynamic loading when JVM interprets the corresponding statement "System.out.println(...)" from specified JRE routine. Or just execute the the println contained in A.class file?
EDIT: Can I say JAVA IS DYNAMICALLY LINKING STANDARD LIBRARIES? –
I want to know whether A.class contains the library function println?
No it doesn't. If you are keen, you can use the javap command (or a decompiler) to see what is inside a class file.
A derived question is how the JVM get function println?
It is loaded from the "rt.jar" file that forms part of the JRE / JDK you are using to run the program.
That's one reason why you need to install a JRE/JDK to run Java code ...