클래스 작동 방식에 대해 배우려고합니다. 이 코드바이트 코드 생성에서 최종 필드 값이 작동하지 않습니다.
dout.writeShort(1);//field count
dout.writeShort(Modifier.PUBLIC|Modifier.STATIC|Modifier.FINAL);//modifiers
dout.writeShort(utfConstant("jjj"));//name
dout.writeShort(utfConstant("I"));//signature
dout.writeShort(1);//attribute count
dout.writeShort(utfConstant("ConstantValue"));//constant value attribute
dout.writeShort(2);//size of attribute
dout.writeShort(intConstant(8));//value
를 사용하여 내 클래스에 최종 필드를 추가하려고하지만 난 그것을 여기에
Exception in thread "main" java.lang.ClassFormatError: Invalid ConstantValue field attribute length 131082 in class file Test
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at Bytecode.BytecodeTest$BytecodeClassLoader.buildClass(BytecodeTest.java:161)
at Bytecode.BytecodeTest.makeClass(BytecodeTest.java:39)
at Bytecode.BytecodeTest.buildClass(BytecodeTest.java:24)
at Bytecode.BytecodeTest.main(BytecodeTest.java:17)
를 컴파일 할 때이 오류를 얻고 나의 다른 코드
private void writeConstantPool(DataOutputStream dout) throws IOException
{
dout.writeShort(poolIndex);
for (Data data : poolMap)
{
int tag = (byte) data.getData()[0];
dout.writeByte(tag);
switch (tag)
{
case CONSTANT_Utf8:
dout.writeUTF((String) data.getData()[1]);
break;
case CONSTANT_Class:
dout.writeShort((Integer) data.getData()[1]);
break;
case CONSTANT_Integer:
dout.writeInt((Integer) data.getData()[1]);
break;
default:
throw new RuntimeException();
}
}
}
private int utfConstant(String s)
{
return constant(CONSTANT_Utf8, s);
}
private int intConstant(int i)
{
return constant(CONSTANT_Integer, i);
}
private int classConstant(String s)
{
int classNameIndex = utfConstant(s.replace('.', '/'));
return constant(CONSTANT_Class, classNameIndex);
}
private int constant(Object... data)
{
Data constantData = new Data(data);
if (poolMap.contains(constantData))
return poolMap.indexOf(constantData)+1;
poolMap.add(poolIndex-1, constantData);
return poolIndex++;
}
private final Stack<Data> poolMap = new Stack<Data>();
private int poolIndex = 1;
private static class Data
{
private Object[] data;
public Data(Object... data)
{
this.data = data;
}
public Object[] getData()
{
return data;
}
public boolean equals(Object o)
{
if(o instanceof Data)
{
Data other = (Data) o;
return Arrays.equals(data, other.getData());
}
return false;
}
}
이 일을하는 방법은 모든 메서드와 필드를 생성하고 다음 상수 풀을 생성하는 것입니다 그리고 바이트 배열의 메서드 및 필드 전에 상수 풀 퍼팅 오전.
누구든지 내가 무엇을 잘못하고 있는지 말할 수 있습니다. 필요한 경우 더 많은 코드를 표시 할 수 있습니다. 또한 문제가 intConstant 또는 상수 값 특성과 같을 수 있다고 생각합니다.
바이트 코드 편집기로 이것을 살펴본 후 intConstant 메소드가 잘 작동하는 것처럼 보이므로 필드 코드가 작동하지 않는다고 생각합니다. 또한 바이트 코드 편집기에서 상수를 살펴 보았는데 혼동스러워 보였습니다.
한 번 바이트 코드 조작을해야했는데, 내가 한 일은 바이트 코드에서 원했던 것과 동등한 소스 코드가 들어있는 간단한 자바 클래스를 작성하는 것이 었습니다. 그 클래스를 컴파일 한 다음 javap을 사용하여 바이트 코드를 확인했습니다. 또한 JVM 사양도 매우 유용 할 수 있습니다. – user3001
나는 둘 다 시도하고 바이트 코드에서 상수 값 특성을 살펴 봤는데 아직도 내가 뭘 잘못하고 있는지 볼 수 없습니다. – Popgalop
클래스 파일 자체를 게시 할 수 있습니까? 무엇이 잘못되었는지 살펴볼 수 있습니다. – Antimony