Java 如何在不进行反编译的情况下更改已编译的.class文件?

Java 如何在不进行反编译的情况下更改已编译的.class文件?,java,ubuntu,decompiling,decompiler,.class-file,Java,Ubuntu,Decompiling,Decompiler,.class File,我想更改.class文件的方法。我安装了JDEclipse反编译器并打开了.class文件。我添加了一些代码并保存了.class文件。但是,.class文件没有更改 我不知道如何使用反编译器。如果可能的话,如何在不使用反编译器的情况下更改.class文件 我正在使用Ubuntu 问候 编辑: 以下是我的反编译代码: /* */ package org.hibernate.id; /* */ /* */ import java.io.Serializable; /*

我想更改.class文件的方法。我安装了JDEclipse反编译器并打开了.class文件。我添加了一些代码并保存了.class文件。但是,.class文件没有更改

我不知道如何使用反编译器。如果可能的话,如何在不使用反编译器的情况下更改.class文件

我正在使用Ubuntu

问候

编辑:

以下是我的反编译代码:

/*     */ 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);
   }
 }

使用字节码编辑器,如:

要小心,因为您需要非常熟悉Java字节码


您还可以在运行时使用字节码编织(如AspectJ)更改类。

您可以在反编译时更改代码,但必须将其重新编译为
文件,反编译器输出
java
代码,必须使用与原始
jar
/
class
文件相同的类路径重新编译

我添加了一些代码并保存了.class文件


您在JDEclipse反编译器中看到的是.class文件中字节码的反编译表示。即使更改文本,也不会影响字节码。

您可以按照以下步骤修改java类:

  • 按您所做的方式反编译.class文件,并将其另存为.java
  • 使用该java文件(原始JAR)在Eclipse中创建一个项目 作为库及其所有依赖项
  • 更改.java并编译
  • 获取修改后的.class文件并将其再次放入原始文件中 罐子

  • 当您反编译并更改代码时,您必须进入eclipse项目的根文件夹,并检查bin文件夹中的类,该文件夹与src处于同一级别。然后用zip工具打开原来的jar(这很好),并将修改后的类放在jar中的同一个包中。

    据我所知,没有简单的方法可以做到这一点。最简单的方法不是将类文件实际转换为可执行文件,而是围绕类文件包装一个可执行启动器。也就是说,创建一个可执行文件(可能是一个基于操作系统的可执行脚本文件),它只需通过命令行调用Java类

    如果你真的想有一个程序来做这件事,你应该看看外面的一些自动安装程序

    以下是我发现的一种方法:

    [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]`
    
    [代码]
    导入java.io.*;
    导入java.util.jar.*;
    类onlyText实现FilenameFilter{
    字符串扩展;
    仅限公共文本(字符串文本){
    this.ext=“.”+ext;
    }
    @凌驾
    公共布尔接受(文件目录,字符串名称){
    返回名称。endsWith(ext);
    }
    }
    公共类执行器{
    公共静态int缓冲区=10240;
    受保护的void创建(文件exefile,文件[]列表文件){
    试一试{
    字节b[]=新字节[缓冲区];
    FileOutputStream fout=新的FileOutputStream(exefile);
    JarOutputStream out=新的JarOutputStream(fout,new Manifest());
    对于(int i=0;i如果(len使用java assistjava库来操作应用程序的java字节码(.class文件)

    ->Spring、Hibernate和EJB使用此代理实现

    ->我们可以通过字节码操作来做一些程序分析


    ->我们可以使用Javassist来实现方法返回值的透明缓存,方法是拦截所有方法调用,并在第一次调用时仅将其委托给超级实现。

    您可以使用任何反编译器来首先反编译文件

    我曾经遇到过一个类似的问题,我没有应用程序的源代码,不得不在文件中做一个很小的更改

    以下是我所做的:

  • 从jar中提取类文件

  • 在反编译器中打开它(我使用JDGUI,您可以从internet上的许多资源中轻松获得) 你可以从

  • 实际上,您可以使用JDGUI查看jar中的所有文件

  • 对我想要的文件进行了更改,并从该文件复制了所有代码
  • 在eclipse中创建了一个新项目,其中只有这个类(,与jar中的包结构相同)),提供了原始jar作为库和所有其他依赖项
  • 编译类,将.class文件从我工作区的bin文件夹注入到jar中
  • 测试我的变化,喝一杯咖啡庆祝:)

  • 有时我们需要从数千个文件中编译一个文件来解决问题。在这种情况下,我们可以创建相同的文件夹结构,如类路径,将文件反编译为java或从源代码复制java文件。进行必要的更改,将一个特定文件编译为类,并保留所有依赖项/类,最后替换class文件。最后重新启动容器。一旦war被分解,文件将不会被替换。

    为什么要这样做?因为idgenerator类不支持BigDecimal。我使用Hibernate和PostgreSQL,我得到以下错误:此id生成器使用反编译器生成长、整数、短或字符串比其他方法简单100倍。如果如果你想多使用反编译器,我会尝试另一种不涉及更改类的方法。当然,我会很高兴。谢谢你的回复,但我对java字节码一无所知。我认为你不能在运行时使用反射更改任何类。你需要一个库来动态创建类来执行类似的操作。有时更改java字节码比正确获取依赖项更容易…特别是如果您只需要进行一些小的更改。JBE在我的案例中出现了错误,但工作得很好。谢谢,我理解这个想法。但我不知道如何做到这一点?拉反编译