how to compile extended class in java? - java

i want to compile child.java class an get child.class, child class extends parent class.
i want child.class include all necessary code from parent class, in fact i can use it independently.
is it possible?
second Question: suppose we have a .jar library containing a.class , b.class , c.class ... i have make an updated version of a.class, how can i replace the new one with the original a.class in jar? is it possible ?
sorry for bad English.

1) as Dmitry mentioned in the comment is impossible. Even if your parent class did absolutely nothing it's definition will still be checked, and if not found ClassNotFoundException (or similar) will be thrown
2) Is certainly possible and usefull in some situations (patching external library without recompiling everything from sources comes to mind) - see Is there are way to patch jar files?
Specifically the most usefull (IMO) is CoolBeans's answer:
jar uf test.jar com\test\Test.class
Note that you have to take care of correct packaging. And it will not work if the jar is signed.

Related

Proguard move all obfuscated class to one package

By now I can keep some classes and methods etc via proguard, now that obfuscation works perfectly here is my question, I've noticed proguard happens to repackage some classes like this com.a.a, com.a.b, is there a way to avoid leaving hints like com.x.x and put all of the obfuscated classes in one package like a.a.**? (real life example of a hint I've seen looks like org.apache.a.x, anyone decompiling my code will immediately skip that particular package because it reeks of library jar, i want to merge obfuscated library and obfuscated original code into one package). i tried this config but it didn't work.
-allowaccessmodification
-mergeinterfacesaggressively
-useuniqueclassmembernames
-keeppackagenames doNotKeepAThing
-repackageclasses
this didn't put obscufated classes on a particular package, but this is what I intended to do, the remaining packages you see there are the ones I've explicitly kept, also if you have resources (files) embedded in a package those would still be retained in it original package structure but their obscufated .class files will be moved to the root
Update 1
yes you can, code below will move obfuscated classes from root to package a.a
-repackageclasses a/a

Validate Java Classes Inside Jar

Java class files inside jars can be easily replaced and modified. For instance, the following command can be used to replace a compiled class file within a jar:
jar uf JarFile.jar com\something\Class.class
If the class file was replaced with a file such that no dependencies were broken, then the code is still able to execute. The same happens with class files that are not inside jars.
Is there any way to validate a set of class files (whether inside a jar or not) to see if all their dependencies are present and not broken?
I do not want to prevent class files from being modified but rather to be able to verify that changes are valid (with respect to dependencies). The compiler does this check (dependency-check) at compile time, but once the classes are compiled, how can one verify the class files themselves?
You might have sealing and signing JARs in mind.
Update:
Apparently I've missed the mark with my first guess.
What do you plan to do if they're not? If they're a 3rd party, I'd say that you've got little choice besides reporting to the bug database that the download is bad.
If you mean "I want to make sure that all their 3rd party JAR dependencies are correct", you've got a much bigger problem. Most downloads that I know of (e.g. Spring) make dependencies available using Maven. That's the best you can do.
If you mean you want to check your own dependencies, I'd say that testing would reveal any errors you've made.
Just loading the class will ensure that.
no, you cannot.
at least: not really.
the problem is that java loads classes at runtime only when needed. so eventually it might be alright to remove a class from the jar file and as long as no code referencing that class is executed things run very smoothly.
consider this example:
class A{ public static void main( String args[] ){ out.println( "hello" ); } }
class B{}
compile this, put it in a jar, remove the B.class from it, no problem there :)
now you might think you can go through each .class file, check what classes it references and see if the files are all there. not only is this painful, it is also incomplete. you will never quite catch files loaded with reflection because their class names might be constructed just at runtime.
my advice: don't go there. if someone removes a class file it's their own fault.
the best thing you can do is (but only if this really really worries you) try to catch ClassNotFoundExceptions at runtime (look into thread.setUncaughtExceptionHandler)

How do I prevent implicit Java compilation when the class exists in the classpath?

Let's say that I have two classes (Bob and Tom) such that Bob uses Tom, but Tom does not require Bob. Both of these files are located in the same directory structure.
public class Bob {
public static void main(String[] args) {
System.out.println(Tom.MESSAGE);
}
}
public class Tom {
public static String MESSAGE = "Hello World";
}
If I attempt to compile Bob in the typical fashion, I can get it to implicitly compile Tom.java as well since it is recognized as a dependency of Bob.java. That works great.
But now let's say that I want to place Tom in a JAR file. So I build Tom.java and place the results into a JAR file: libTom.jar. I now compile with the classpath pointing at libTom.jar. Unfortunately, the compiler sees the Tom.java file and causes it to be compiled rather than using the class in libTom.jar. Is there a way to get the compiler to skip the implicit construction of Tom.java if the class is found in the classpath?
I recognize that this example is fairly contrived. Rest assured that there is a more complicated, less contrived use-case that surrounds this issue. Thanks.
If there are two classes with the same name and in the same package in the classpath, it is difficult to predict which one will get picked up when java compiles the code. In case the Tom class exists in the source itself, it will surely get picked up.
One way you can avoid it is to put one of the Toms in a different package. Another way is if you can move your current Tom to a separate project. I understand either of these might not be practical for you. If it is really necessary, you could experiment with writing your own ClassLoader. See this question for reference: Jar hell: how to use a classloader to replace one jar library version with another at runtime
It appears that this just isn't possible, which is what I feared from the beginning.
Yes, you could do that by typing the full name of a class, i.e. Typing
System.out.println(the.package.of.external.Tom.MESSAGE);
System.out.println(the.current.package.Tom.MESSAGE);
Can you split the java files into separate source directories?
This would make sense as you could build your jar from the contents of one source dir, then just include the other source dir when compiling all the other set of files.
This works well in Eclipse.
Even better would be to use two projects in Eclipse.

Java Subclass $

I am new to Java and might be asking a basic question which might sound silly to some.
After I compile my Main Java class most of the subclasses are displayed as $ in the folder. I copy the complied classes and put it on another location to execute. Everytime I make make a change to the main class or one of the sub classes do I need to copy all the associated subclasses? or just copying the changed ones will do?
Thanks.
Nick
Copying the changes will do.
Normally, you would let your IDE (e.g., Netbeans) / build system (e.g., Ant / Maven) do this for you. Alternatively you could create an executable jar-file, leaving you with only one file to copy.
Classnames containing $ are for nested/anonymous classes.
And see this Stackoverflow question.
But that's not the whole point. Quoting OP I copy the complied classes and put it on another location to execute. -- looks like you should automate this task and employ one of traditional Java build tools such as Ant or Maven.
Nick,
Are you referring to nested classes? If so, they will contain "$" in the compiled class file names. Assuming your code changes were only to the parent class, the nested class bytecode should not have changed during the recompilation. It should work to only copy the main .class file. However, it's obviously more of a guarantee to copy the everything.
Is this about subclassing (class Y extends X {}), or nested classes (class Y { class X {} })?
The $ that you mention seems to indicate the latter, in which case you should probably copy everything, but if you are only subclassing then just copying the compiled versions of the files you have changed is probably just fine.

NoSuchMethodErrors say the darndest things

So, I'm working in eclipse were everything compiles and runs correctly. However, when compiling under ant for the build server, A large number of tests fail with a NoSuchMethodError saying:
class A implements B
interface B extends C
C requires method getSyncID() // standard getter for an int field.
A.java contains getSyncID()
A.class contains getSyncID()
and yet the Error is still thrown.
Does anyone know how the hell this could happen? how to fix it.
This happens when class files get out of sync with each other; in other words, one was compiled to a new version while another one wasn't. Try cleaning and rebuilding from scratch.
The problem occurs when the class loader discovers that a method in one class (A) calls a method in another class (B) that does not exist. The root cause is that the class B that the class loader sees is different to the class B that the compiler saw when it compiled A.
The most common cause of this problem is as #MarkPeters says - that your ".class" files have gotten out of sync with the ".java" files and need to be recompiled from scratch.
Another possibility is that you have an old copy of some of the ".class" files on the classpath when you try to run the application.
But either way, you have to believe the classloader. If it says that the method is not there, then it is not there ... in the particular ".class" file that it is loading. If the method appears to be there in the ".class" file, then that is evidence that you are loading a different version of the file earlier in the classpath!

Categories

Resources