2012-12-28 15 views
22

Chcę zmienić metodę pliku .class. Zainstalowałem JD Eclipse Decompiler i otworzyłem plik .class. Dodałem kilka kodów i zapisz plik .class. Ale plik .class się nie zmienia.Jak zmienić już skompilowany plik .class bez dekompilacji?

Nie wiem, jak korzystać z dekompilatora. A jeśli to możliwe, jak zmienić plik .class bez użycia dekompilatora.

Używam Ubuntu.

Pozdrowienia

EDIT:

Oto moja dekompilowana Kod:

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

dlaczego chcesz to zrobić? –

+1

Ponieważ klasa idgenerator nie obsługuje BigDecimal. Używam Hibernate i PostgreSQL i otrzymuję ten błąd: ten id generator generuje długi, całkowity, krótki lub ciąg –

+3

Korzystanie z dekompilatora jest 100 razy łatwiejsze niż alternatywy. Jeśli znajdziesz pomysł na użycie dekompilatora, spróbuję innego podejścia, które nie wymaga zmiany klasy. –

Odpowiedz

8

pomocą edytora kodu bajtowego, jak:

http://set.ee/jbe/

Bądź ostrożny, ponieważ potrzebny jest bardzo dobra znajomość kodu bajtowego Java.

Możesz również zmienić klasę w czasie wykonywania z tkaniem kodu bajtowego (np. AspectJ).

+1

Dzięki za odpowiedź, ale nie mam wiedzy na temat bajtów Java. –

+2

Nie sądzę, że możesz zmienić dowolną klasę w środowisku wykonawczym z refleksją. Potrzebujesz biblioteki do tworzenia zajęć w locie, aby zrobić coś podobnego. – izaera

0

Można zmienić kod kiedy go dekompilować, ale to musi być ponownie skompilowana do pliku class, wyjścia Decompiler kod java, to musi być ponownie skompilowana z tej samej ścieżce klasy jako oryginalny jar/class pliku

+0

Dzięki, zrozumiałem ten pomysł. Ale nie wiem, jak to robię? –

+0

ściągnij kod dekompilowany do zaćmienia, rozwiązuj zależności, napraw błędy i przekompiluj za pomocą środowiska Eclipse. wstaw plik wynikowy klasy do starego słoika. alternatywnie uzyskaj oryginalny kod źródłowy. – epoch

+0

Mogę osiągnąć plik .java pliku .class tylko w Eclipse. Więc nie rozumiem, w jaki sposób "plik klasy do starego słoika"? –

3

Dodałem kilka kodów i zapisz plik .class.

To, co widzisz w JD Eclipse Decompiler, to dekompilowana reprezentacja kodu bajtowego w pliku .class. Nawet jeśli zmienisz tekst, nie wpłynie to na kod bajtowy.

+0

To jest mój problem. Zmieniłem, ale nie efekt. –

+0

@BreedHansen, dlaczego nie generować ciągów zamiast BigDecimal? Tak więc odpowiedź na twoje pytanie brzmi: jest prawie niemożliwe. Lub musisz wyodrębnić kod źródłowy do zaćmienia i spróbować wygenerować inny plik klasy ze swoimi modyfikacjami. –

+0

Dzięki za szczegółową odpowiedź. Chce to zrobić. Czy to naprawdę niemożliwe? https://forum.hibernate.org/viewtopic.php?t=964410 –

29

Możesz śledzić kroki, aby modyfikować swoją klasę Java:

  1. dekompilacji pliku .class jak masz zrobić i zapisać go jako .java
  2. Tworzenie projektu w Eclipse z tego pliku Java, Oryginalny JAR jak biblioteki, a wszystkie jego zależności
  3. Zmiany .java i skompilować
  4. Pobierz plik zmodyfikowany .class i umieścić ją ponownie wewnątrz oryginalnego JAR.
+0

Nie mogę zapisać pliku .java. Właściwie to nie mogę zapisać. Zapisałem plik .class, ale po zamknięciu i ponownym otwarciu moje zmiany zniknęły. –

+0

Czy możesz skopiować i wkleić zdekompilowany kod źródłowy? – izaera

+0

Czy nie byłoby lepiej pobrać kod źródłowy pliku, który chcesz zmodyfikować (ponieważ jest on częścią Hibernate), zmienić go i przekompilować? Możesz użyć mojej metody do rekompilacji lub po prostu spróbować przekompilować cały Hibernate (choć może to być trudniejsze). – izaera

2

po dekompilacji i zmianie kodu należy przejść do folderu głównego projektu zaćmienia i sprawdzić klasę w folderze bin, który znajduje się na tym samym poziomie, co src. następnie otwórz oryginalny słoik z narzędziem zip (7zip jest na to dobry) i umieść zmodyfikowaną klasę w tym samym pakiecie wewnątrz słoika.

0

O ile się dowiedziałem, nie ma prostego sposobu na zrobienie tego. Najprościej jest nie przekonwertować pliku klasy na plik wykonywalny, ale owinąć plik wykonywalny wokół pliku klasy. To znaczy, utwórz plik wykonywalny (być może oparty na systemie operacyjnym plik wykonywalny skryptów), który po prostu wywołuje klasę Java za pomocą wiersza poleceń.

Jeśli chcesz mieć program, który to robi, powinieneś zajrzeć do niektórych zautomatyzowanych instalatorów.

Oto sposób znalazłem:

[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]` 
1

Zastosowanie java pomagać biblioteki Java dla manipulacji kodu bajtowego Java (.class plik) wniosku.

-> Wiosna, Hibernate, EJB przy użyciu tego wdrożenia proxy

-> możemy kod bajtowy manipulacji zrobić kilka Analysis Program

-> możemy użyć Javassist wdrożyć przejrzyste cache dla wartości zwracanych metoda , przechwytując wszystkie wywołania metod i delegując tylko do super implementacji przy pierwszym wywołaniu.

0

Możesz użyć dowolnego dekompilatora do pierwszej dekompilacji pliku.

Raz spotkałem się z problemem simillar, w którym nie miałem kodu źródłowego aplikacji i musiałem wprowadzić bardzo małą zmianę w pliku.

Poniżej jest to, co robiłam:

  1. wyjął plik klasy ze słoika

  2. otworzył ją w dekompilator (używam JD GUI, można dostać go łatwo z wiele zasobów w Internecie) Możesz pobrać go od here

  3. Możesz zobaczyć wszystkie Pliki w słoiku za pomocą interfejsu JD GUI.

  4. wprowadzone zmiany w pliku chciałem i skopiowany cały kod z tego pliku
  5. utworzony nowy projekt w Eclipse tylko z tej klasy (o takiej samej strukturze pakietu jak w słoiku), pod warunkiem, że oryginał jar jako biblioteka i wszystkie inne zależności.
  6. Zestawione klasę, wstrzykuje plik .class z powrotem do słoika z katalogu bin mojego roboczej
  7. Testowany moją zmianę, obchodził go przez popijając kawę :)
0

Jakiś czas musimy skompilować jeden plik z tysiąca plików, aby naprawić problem. W takim przypadku można stworzyć taką samą strukturę folderów jak ścieżka klas, dekompilować plik do java lub skopiować plik java z kodu źródłowego. Wprowadź wymagane zmiany, skompiluj jeden konkretny plik do klasy z wszystkimi zależnościami/klasami i ostatecznie zastąp plik klasy. Na koniec zrestartuj kontener. Po wybuchu wojny plik nie zostanie zastąpiony.

Powiązane problemy