It's possible to save class from URLClassLoader to normal file.class? and then decompile it?
I trying save it just as object using
Class<?> clazz = classLoader.loadClass("foo.Bar");
FileOutputStream sf = new FileOutputStream(f);
ObjectOutputStream s = new ObjectOutputStream(sf);
s.writeObject(clazz);
s.close();
Bu that don't work.
So... how to decompile it? I need get something like result of jd-gui, but using class from URLClassLoader.
You need to map the class name (e.g. "foo.Bar") to a resource path name (e.g. "/foo/Bar.class") and then use classLoader.getResourceAsStream to open a stream to read the bytecode file.
In theory, this can then be fed to a decompiler ... assuming that you have a decompiler that can read from an InputStream.
What you are doing at the moment fails because a Class object cannot be serialized.
Do a simple HTTP download, rather than URLClassLoader, to get the class into a file. Then decompile that.
(Writing an object to an ObjectOutputStream only saves the data in an instance of the object, and even that works only if the object has implemented Serializable. Not what you're looking for here.)
Related
I am trying to open a file for reading or create the file if it was not there.
I use this code:
String location = "/test1/test2/test3/";
new File(location).mkdirs();
location += "fileName.properties";
Path confDir = Paths.get(location);
InputStream in = Files.newInputStream(confDir, StandardOpenOption.CREATE);
in.close();
And I get java.nio.file.NoSuchFileException
Considering that I am using StandardOpenOption.CREATE option, the file should be created if it is not there.
Any idea why I am getting this exception?
It seems that you want one of two quite separate things to happen:
If the file exists, read it; or
If the file does not exist, create it.
The two things are mutually exclusive but you seem to have confusingly merged them. If the file did not exist and you've just created it, there's no point in reading it. So keep the two things separate:
Path confDir = Paths.get("/test1/test2/test3");
Files.createDirectories(confDir);
Path confFile = confDir.resolve("filename.properties");
if (Files.exists(confFile))
try (InputStream in = Files.newInputStream(confFile)) {
// Use the InputStream...
}
else
Files.createFile(confFile);
Notice also that it's better to use "try-with-resources" instead of manually closing the InputStream.
Accordingly to the JavaDocs you should have used newOutputStream() method instead, and then you will create the file:
OutputStream out = Files.newOutputStream(confDir, StandardOpenOption.CREATE);
out.close();
JavaDocs:
// Opens a file, returning an input stream to read from the file.
static InputStream newInputStream(Path path, OpenOption... options)
// Opens or creates a file, returning an output stream that
// may be used to write bytes to the file.
static OutputStream newOutputStream(Path path, OpenOption... options)
The explanation is that OpenOption constants usage relies on wether you are going to use it within a write(output) stream or a read(input) stream. This explains why OpenOption.CREATE only works deliberatery with the OutputStream but not with InputStream.
NOTE: I agree with #EJP, you should take a look to Oracle's tutorials to create files properly.
I think you intended to create an OutputStream (for writing to) instead of an InputStream (which is for reading)
Another handy way of creating an empty file is using apache-commons FileUtils like this
FileUtils.touch(new File("/test1/test2/test3/fileName.properties"));
Hello every I have a query for creating FILE using FILE CLASS & FILEOUTPUTSTREAM CLASS . I know using FILE CLASS we have to use method name createfile to create an specific file and when we are using FILEOUTPUTSTREAM CLASS then we pass string path or name with in the class initialization then that file created automatic. But Then What is Different between both the cases?
A File is an abstract path. It has no physical existence.
It is only when "using" that File that the underlying physical storage is actually hit.
A FileOutputStream will handle file existence test/creation/opening etc for you.
Note: if you use Java 7, ditch File and use Path instead.
The File class is just a handle for the file. The FileOutputStream is an OutputStream that you can write to: FileOutputStream JavaDoc.
You can think of them as touch myfile.txt vs. echo > myfile.txt
I have an issue while reading the data from a file using objectInputStream. Please find the code below
File file = new File("model.pst")
if (file.exists()) {
fis = new FileInputStream(file);
in = new ObjectInputStream(fis);
input = (List<GlobalModel>) in.readObject();
in.close();
}
I got to know from the ObjectOutputStream http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html docs, that while writing the object to the file, he default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields.I have an issue where the class name has been changed after writing the object to the file and when I use the above code to read the values, its throwing a classNotFound exception. I would like to know if there is a way, I can handle this exception, i.e once it comes to the exception block, can I replace the classname in the object that is being read to the new class name and make it work ?
Please Assist. Thanks in Advance
I've never done this myself but it should be possible to replace a class by another by making a subclass of object input stream and overriding the resolveClass method, http://docs.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html#resolveClass(java.io.ObjectStreamClass)
Is it possible to change the filepath of the File class in java without creating a new instance?
File file = new File(System.getProperty("user.home")); <br>
System.out.println(file.getPath());
returns C:\Users\username
now I want to go to the parent directory. I thought I could use something like this
file.setPath(file.getParent());
but I have to use
file = new File(file.getParent());
any other way I can achieve the same? Or maybe I could create multiple instances, store them in an array and work with two objects (directories) at the same time?
From the javadocs:
Instances of the File class are immutable; that is, once created, the abstract pathname represented by a File object will never change.
So, no, you can't change a File instance. If you want a different value, you have to instantiate a new File.
Apparently you missed File.getParentFile():
file = file.getParentFile();
My question is how to get an instance of java.lang.Class from a given .class file?
So if I have the file MyClass.class, and the corresponding java.io.File instance, how can I use this to get an instance of java.lang.Class that corresponds to MyClass?
Class<?> clazz = new URLClassLoader(new File("").toURL()).loadClass(className);
You actually need a classloader to do this (to turn a byte-code byte-stream into a class). There a few options here. One, you use a standard URLClassLoader instance, but that would rely on your being placed in a good java package location (you would create the URLClassLoader to the root of your file path in which you file resides. But this would only work when the directory structure mirrors the package structure of the class file you are trying to load).
The easiest base class would be SecureClassLoader as that allows you to run your code in a JVM with a security manager enabled (iow, you can set the code base)
The important method for you is the findClass as that would turn a binary name into a class (you can make your own mapping between the classname and the file your are loading). You can load the File and pass the bytes of the file to the most important method: defineClass. This is a method of the SecureClassLoader. It takes a binary name of your class, the ByteBuffer and a CodeSource (for Java Security)
To create a buffer from your file use:
FileInputStream fis = new FileInputStream(yourFileObj)
FileChannel channel = fis.getChannel();
ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, clsFile.length());
You need a CodeSource so you can use it in a secure environment, you might want to use something like:
CodeSource cs = new CodeSource(clsFile.getParent().toURI().toURL(), (CodeSigner[]) null);
and then invoke the
Class<?> aClass = super.defineClass(name, buffer, cs);
Hope this puts you into the right direction(!)