41

I want to change .class file's method. I installed JD Eclipse Decompiler and opened the .class file. I added some codes and save .class file. But, .class file is not changing.

I don't know how to use decompiler. And if is it possible, how to change .class file without using decompiler.

I am using Ubuntu.

Regards

EDIT:

Here is my decompiled code:

/*     */ package org.hibernate.id;
/*     */ 
/*     */ import java.io.Serializable;
/*     */ import java.sql.ResultSet;
/*     */ import java.sql.SQLException;
/*     */ import java.util.HashMap;
/*     */ import java.util.Properties;
/*     */ import org.apache.commons.logging.Log;
/*     */ import org.apache.commons.logging.LogFactory;
/*     */ import org.hibernate.HibernateException;
/*     */ import org.hibernate.MappingException;
/*     */ import org.hibernate.dialect.Dialect;
/*     */ import org.hibernate.type.Type;
/*     */ import org.hibernate.util.ReflectHelper;
/*     */ 
/*     */ public final class IdentifierGeneratorFactory
/*     */ {
/*  25 */   private static final Log log = LogFactory.getLog(IdentifierGeneratorFactory.class);
/*     */ 
/*  64 */   private static final HashMap GENERATORS = new HashMap();
/*     */ 
/*  66 */   public static final Serializable SHORT_CIRCUIT_INDICATOR = new Serializable() {
/*     */     public String toString() { return "SHORT_CIRCUIT_INDICATOR";
/*     */     }
/*  66 */   };
/*     */ 
/*  70 */   public static final Serializable POST_INSERT_INDICATOR = new Serializable() {
/*     */     public String toString() { return "POST_INSERT_INDICATOR";
/*     */     }
/*  70 */   };
/*     */ 
/*     */   public static Serializable getGeneratedIdentity(ResultSet rs, Type type)
/*     */     throws SQLException, HibernateException, IdentifierGenerationException
/*     */   {
/*  32 */     if (!(rs.next())) {
/*  33 */       throw new HibernateException("The database returned no natively generated identity value");
/*     */     }
/*  35 */     Serializable id = get(rs, type);
/*     */ 
/*  37 */     if (log.isDebugEnabled()) log.debug("Natively generated identity: " + id);
/*  38 */     return id;
/*     */   }
/*     */ 
/*     */   public static Serializable get(ResultSet rs, Type type)
/*     */     throws SQLException, IdentifierGenerationException
/*     */   {
/*  45 */     Class clazz = type.getReturnedClass();
/*  46 */     if (clazz == Long.class) {
/*  47 */       return new Long(rs.getLong(1));
/*     */     }
/*  49 */     if (clazz == Integer.class) {
/*  50 */       return new Integer(rs.getInt(1));
/*     */     }
/*  52 */     if (clazz == Short.class) {
/*  53 */       return new Short(rs.getShort(1));
/*     */     }
/*  55 */     if (clazz == String.class) {
/*  56 */       return rs.getString(1);
/*     */     }
                if(clazz == java.math.BigDecimal.class){
                    return rs.getBigDecimal(1);
                }
/*     */ 
/*  59 */     throw new IdentifierGenerationException("this id generator generates long, integer, short or string78");
/*     */   }
/*     */ 
/*     */   public static IdentifierGenerator create(String strategy, Type type, Properties params, Dialect dialect)
/*     */     throws MappingException
/*     */   {
/*     */     try
/*     */     {
/*  92 */       Class clazz = getIdentifierGeneratorClass(strategy, dialect);
/*  93 */       IdentifierGenerator idgen = (IdentifierGenerator)clazz.newInstance();
/*  94 */       if (idgen instanceof Configurable) ((Configurable)idgen).configure(type, params, dialect);
/*  95 */       return idgen;
/*     */     }
/*     */     catch (Exception e) {
/*  98 */       throw new MappingException("could not instantiate id generator", e);
/*     */     }
/*     */   }
/*     */ 
/*     */   public static Class getIdentifierGeneratorClass(String strategy, Dialect dialect) {
/* 103 */     Class clazz = (Class)GENERATORS.get(strategy);
/* 104 */     if ("native".equals(strategy)) clazz = dialect.getNativeIdentifierGeneratorClass();
/*     */     try {
/* 106 */       if (clazz == null) clazz = ReflectHelper.classForName(strategy);
/*     */     }
/*     */     catch (ClassNotFoundException e) {
/* 109 */       throw new MappingException("could not interpret id generator strategy: " + strategy);
/*     */     }
/* 111 */     return clazz;
/*     */   }
/*     */ 
/*     */   public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
/* 115 */     if (clazz == Long.class) {
/* 116 */       return new Long(value);
/*     */     }
/* 118 */     if (clazz == Integer.class) {
/* 119 */       return new Integer((int)value);
/*     */     }
/* 121 */     if (clazz == Short.class) {
/* 122 */       return new Short((short)(int)value);
/*     */     }

/*     */ 
/* 125 */     throw new IdentifierGenerationException("this id generator generates long, integer, short");
/*     */   }
/*     */ 
/*     */   static
/*     */   {
/*  75 */     GENERATORS.put("uuid", UUIDHexGenerator.class);
    GENERATORS.put("hilo", TableHiLoGenerator.class);
     GENERATORS.put("assigned", Assigned.class);
     GENERATORS.put("identity", IdentityGenerator.class);
    GENERATORS.put("select", SelectGenerator.class);
    GENERATORS.put("sequence", SequenceGenerator.class);
     GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);
    GENERATORS.put("increment", IncrementGenerator.class);
   GENERATORS.put("foreign", ForeignGenerator.class);
     GENERATORS.put("guid", GUIDGenerator.class);
     GENERATORS.put("uuid.hex", UUIDHexGenerator.class);
     GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);
   }
 }
Breed Hansen
  • 1,159
  • 5
  • 13
  • 21

10 Answers10

47

You can follow these steps to modify your java class:

  1. Decompile the .class file as you have done and save it as .java
  2. Create a project in Eclipse with that java file, the original JAR as library, and all its dependencies
  3. Change the .java and compile
  4. Get the modified .class file and put it again inside the original JAR.
xxxxxxxxx
  • 999
  • 5
  • 11
  • I can't save .java file. Actually, i can't save anyway. I saved .class file but when I close and reopen my changes are disappear. – Breed Hansen Dec 28 '12 at 12:20
  • Wouldn't it be better to download the source code for the file you want to modify (as it is part of Hibernate), change it, and recompile? You can use my method to recompile or just try to recompile the whole Hibernate (though this can be harder). – xxxxxxxxx Dec 28 '12 at 13:02
  • Then, you have it. Just save it to a Java file, add the modifications in the forum, and do what I proposed. – xxxxxxxxx Dec 28 '12 at 13:38
  • I can't save. When I close the .class file, changes are disappears. Because I can't recompile. – Breed Hansen Dec 28 '12 at 14:44
  • You forgot one other option. Disassemble, modify, and reassemble. It works on any classfile, but it requires you to understand bytecode, which I highly doubt the OP does. – Antimony Dec 29 '12 at 14:11
  • :-O. Now I understand. I was not stating options, but steps in a process. I was suggesting Breed to follow these steps to modify the java class. – xxxxxxxxx Dec 29 '12 at 18:49
  • @izaera, I did it. My new .class file is shown properly. My edit is saved. But I have a problem. I get same error and when I clicked the error link I get this warning "Source not found for org.hibernate.id.IdGeneratorFactory" I can see .class file but it is not shown runtime. – Breed Hansen Jan 14 '13 at 07:43
16

Use a bytecode editor, like:

http://set.ee/jbe/

Be careful because you need a very good knowledge of the Java bytecode.

You can also change the class at runtime with bytecode weaving (like AspectJ).

Lakatos Gyula
  • 3,949
  • 7
  • 35
  • 56
  • 1
    Thanks for reply but i have no knowledge about java bytecode. – Breed Hansen Dec 28 '12 at 11:54
  • 2
    I don't think you can change any class in runtime with reflection. You need a library to create classes on the fly to do something similar. – xxxxxxxxx Dec 28 '12 at 11:55
  • 1
    Sometimes changing java bytecode is easier than getting dependencies right... Especially if you just have to make some minor changes. JBE threw errors in my case but [Recaf](https://github.com/Col-E/Recaf) worked perfectly. – Nico Schreiner Mar 26 '20 at 17:49
5

Recaf is a decompiler GUI that allows you to edit and recompile files. Here is the relevant portion of the manual:

The easiest way to edit bytecode is to edit it as decompiled source. This does not work for highly complex cases and obfuscation, but for most simple edits its all you’ll ever need to do. Simply open the class, make your changes as plain Java code, and save.

BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
3

I added some codes and save .class file.

What you see in JD EClipse Decompiler is decompiled representation of byte code in the .class file. Even though you change the text it won't affect the byte code.

Nikolay Kuznetsov
  • 9,467
  • 12
  • 55
  • 101
  • That is the my problem. I changed but not effect. – Breed Hansen Dec 28 '12 at 12:10
  • @BreedHansen, why not to generate String instead of BigDecimal? So the answer to your question is: it is almost impossible. Or you have to extract the source code to eclipse and try to generate another class file with your modifications. – Nikolay Kuznetsov Dec 28 '12 at 12:14
  • Thanks for detail reply. I want to do this. Is it really impossible? https://forum.hibernate.org/viewtopic.php?t=964410 – Breed Hansen Dec 28 '12 at 12:18
2

when you decompile and change the code you have to go on the root folder of your eclipse project and check your class in bin folder wich is on the same level as src. then open you original jar with zip tool ( 7zip is good for that ) and put the modified class in tha same package inside the jar.

abk
  • 35
  • 6
2

You can use any decompiler to first decompile the file.

I had once faced a simillar problem where I didn't have source code of the application and had to make a very small change in a file.

Below is what I did:

  1. Extracted the class file from the jar

  2. Opened it in a decompiler (I use JD GUI, you can get it easily from many resources on internet) You may download it from here

  3. You can actually view all the files in a jar using JD GUI.

  4. Made changes to the file I wanted to and copied all the code from that file
  5. Created a new project in eclipse with only this class (with the same package structure as in the jar), provided the original jar as library and all other dependencies.
  6. Compiled the class, injected the .class file back to the jar from bin folder of my workspace
  7. Tested my change, celebrated it by sipping a cup of coffee :)
1

Use java assist Java library for manipulating the Java bytecode (.class file) of an application.

-> Spring , Hibernate , EJB using this for proxy implementation

-> we can bytecode manipulation to do some program analysis

-> we can use Javassist to implement a transparent cache for method return values, by intercepting all method invocations and only delegating to the super implementation on the first invocation.

Vijay
  • 4,694
  • 1
  • 30
  • 38
0

You can change the code when you decompiled it, but it has to be recompiled to a class file, the decompiler outputs java code, this has to be recompiled with the same classpath as the original jar/class file

epoch
  • 16,396
  • 4
  • 43
  • 71
  • Thanks, I understood the idea. But i don't know how i do this? – Breed Hansen Dec 28 '12 at 11:58
  • pull the decompiled code into eclipse, resolve dependencies, fix errors, and recompile with eclipse. put the resulting class file into the old jar. alternatively obtain original source code. – epoch Dec 28 '12 at 12:00
  • I can reach .class file's .java file only in Eclipse. So, i don't understood how "class file into the old jar"? – Breed Hansen Dec 28 '12 at 12:13
0

Sometime we need to compile one single file out of thousand files to fix the problem. In such a case, One can create same folder structure like class path, decompile the file into java or copy java file from source code. Make required changes, compile one particular file into class with all dependency/classes in place and finally replace the class file. Finally restart the container. Once war is exploded file will not be replaced.

-1

As far as I've been able to find out, there is no simple way to do it. The easiest way is to not actually convert the class file into an executable, but to wrap an executable launcher around the class file. That is, create an executable file (perhaps an OS-based, executable scripting file) which simply invokes the Java class through the command line.

If you want to actually have a program that does it, you should look into some of the automated installers out there.

Here is a way I've found:

[code]
import java.io.*;
import java.util.jar.*;

class OnlyExt implements FilenameFilter{
String ext;
public OnlyExt(String ext){
this.ext="." + ext;
}

@Override
public boolean accept(File dir,String name){
return name.endsWith(ext);
}
}

public class ExeCreator {
public static int buffer = 10240;
protected void create(File exefile, File[] listFiles) {
try {
byte b[] = new byte[buffer];
FileOutputStream fout = new FileOutputStream(exefile);
JarOutputStream out = new JarOutputStream(fout, new Manifest());
for (int i = 0; i < listFiles.length; i++) {
if (listFiles[i] == null || !listFiles[i].exists()|| listFiles[i].isDirectory())
System.out.println("Adding " + listFiles[i].getName());
JarEntry addFiles = new JarEntry(listFiles[i].getName());
addFiles.setTime(listFiles[i].lastModified());
out.putNextEntry(addFiles);

FileInputStream fin = new FileInputStream(listFiles[i]);
while (true) {
int len = fin.read(b, 0, b.length);
if (len <= 0)
break;
out.write(b, 0, len);
}
fin.close();
}
out.close();
fout.close();
System.out.println("Jar File is created successfully.");
} catch (Exception ex) {}
}

public static void main(String[]args){
ExeCreator exe=new ExeCreator();
FilenameFilter ff = new OnlyExt("class");
File folder = new File("./examples");
File[] files = folder.listFiles(ff);
File file=new File("examples.exe");
exe.create(file, files);
}

}


[/code]`
kytuni
  • 1