I'm looking for a way to test a java library. I never worked before with libraries written by me, and I'm trying to understand how to debug a java project without a main method. In particular, I took a java library that handles barcodes and I'm trying to change its contents. In the example version there is only a bar code, while I need to implement other types of bar codes. Since in the decompiled library imported into Eclipse there is no Main method to debug the content and see any errors. Operationally how can I do in Eclipse that execute the code, instead of each time exporting the jar file and replacing it in the classpath that containing the original library?
I looked for something online, but I didn't find an example tha t explains how to do.
import com.crystaldecisions.reports.common.CrystalResourcesFactory;
import com.crystaldecisions.reports.common.value.FormulaValue;
import com.crystaldecisions.reports.common.value.FormulaValueType;
import com.crystaldecisions.reports.common.value.StringValue;
import com.crystaldecisions.reports.formulas.FormulaFunction;
import com.crystaldecisions.reports.formulas.FormulaFunctionArgumentDefinition;
import com.crystaldecisions.reports.formulas.FormulaFunctionCallException;
import com.crystaldecisions.reports.formulas.FormulaValueReference;
import com.crystaldecisions.reports.formulas.SimpleFormulaFunctionArgumentDefinition;
public abstract class CodeEAN13Base
implements FormulaFunction
{
FormulaFunctionArgumentDefinition[] myArguments = { SimpleFormulaFunctionArgumentDefinition.string };
protected CrystalResourcesFactory resCrystal;
public CodeEAN13Base()
{
this.resCrystal = new CrystalResourcesFactory("Messages");
}
protected final String doTranslation(String inputData,String opz)
// protected final String doTranslation(String inputData)
{
String returnVal = "";
// returnVal = returnVal + translateCharWrapper(inputData);
returnVal = returnVal + translateCharWrapper(inputData,opz);
return returnVal;
}
#Override
public final FormulaValue evaluate(FormulaValueReference[] arguments)
throws FormulaFunctionCallException
{
StringValue dataStringArg = (StringValue)arguments[0].getFormulaValue();
StringValue opzArg =(StringValue)arguments[1].getFormulaValue();
String dataString = dataStringArg.getString();
String opz=opzArg.getString();
String returnVal = doTranslation(dataString,opz);
return StringValue.fromString(returnVal);
}
#Override
public final FormulaFunctionArgumentDefinition[] getArguments()
{
return this.myArguments;
}
#Override
public final FormulaValueType getReturnType()
{
return FormulaValueType.string;
}
protected abstract String translate(String inputData,String opz)
throws InvalidBarcodeDataException;
//protected abstract String translate(String inputData)
//throws InvalidBarcodeDataException;
// private String translateCharWrapper(String inputData)
private String translateCharWrapper(String inputData,String opz)
{
String returnString;
try
{
// returnString = translate(inputData);
returnString = translate(inputData,opz);
} catch (InvalidBarcodeDataException e) {
returnString = "";
}
return returnString;
}
#Override
public void validateArgumentValues(FormulaValueReference[] arguments)
throws FormulaFunctionCallException
{}
}
Related
I have recently upgraded to latest 4.x version of cucumber-jvm in my project in order to leverage parallel execution feature of cucumber. But I am facing this issue now with respect to having custom data type as parameter. Earlier we had an interface called Transformer which we can implement for custom data types, now in the latest version I've found TypeRegistryConfigurer interface which needs to be implemented. But it is not recognising the step as I would've expected. Details as follows:
Gherkin Step:
Given user gets random(3,true,true) parameter
StepDefinition:
#Given("user gets {random} parameter")
public void paramTest(RandomString randomString) {
System.out.println(randomString.string);
}
RandomString class:
public class RandomString {
public String string;
public RandomString(String string) {
Matcher m = Pattern.compile("random\\((.?)\\)").matcher(string);
String t = "";
while (m.find()) {
t = m.group(1);
}
boolean isAlpha = true, isNum = true;
if (t.length() > 0) {
String[] placeholders = t.split(",");
if (placeholders.length == 3) {
int count = Integer.parseInt(placeholders[0]);
isAlpha = Boolean.valueOf(placeholders[1]);
isNum = Boolean.valueOf(placeholders[2]);
this.string = string.replaceAll("random(.*)", RandomStringUtils.random(count, isAlpha, isNum));
}
}
this.string = string.replaceAll("random(.*)", RandomStringUtils.random(3, isAlpha, isNum));
}
}
TypeRegistryImpl:
public class TypeRegistryConfiguration implements TypeRegistryConfigurer {
#Override
public Locale locale() {
return Locale.ENGLISH;
}
#Override
public void configureTypeRegistry(TypeRegistry typeRegistry) {
typeRegistry.defineParameterType(new ParameterType<>(
"random",
"random([0-9],true|false,true|false)",
RandomString.class,
RandomString::new)
);
}
}
Your string random(3,true,true) does not match the pattern used in:
typeRegistry.defineParameterType(new ParameterType<>(
"random",
"random([0-9],true|false,true|false)",
RandomString.class,
RandomString::new)
);
You can verify this by creating the pattern and testing it:
import java.util.regex.Pattern;
class Scratch {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("random([0-9],true|false,true|false)");
// prints out false
System.out.println(pattern.matcher("random(3,true,true)").matches());
}
}
You have also not used a matching pattern in RandomString.
I've found the solution after trial and hit and going through some examples from some Unit Tests in cucumber-jvm project.
Modified StepDef:
#Given("user gets {random} parameter")
public void paramTest(String randomString) {
System.out.println(randomString.string);
}
TypeRegistryConfigurer Implementation:
import cucumber.api.TypeRegistry;
import cucumber.api.TypeRegistryConfigurer;
import io.cucumber.cucumberexpressions.CaptureGroupTransformer;
import io.cucumber.cucumberexpressions.ParameterType;
import org.apache.commons.lang3.RandomStringUtils;
import java.util.Locale;
public class TypeRegistryConfiguration implements TypeRegistryConfigurer {
#Override
public Locale locale() {
return Locale.ENGLISH;
}
#Override
public void configureTypeRegistry(TypeRegistry typeRegistry) {
typeRegistry.defineParameterType(new ParameterType<>(
"random",
"random\\(([0-9]+),(true|false),(true|false)\\)",
String.class,
new CaptureGroupTransformer<>() {
#Override
public String transform(String[] args) {
return RandomStringUtils.random(Integer.parseInt(args[0]), Boolean.valueOf(args[1]), Boolean.valueOf(args[2]));
}
})
);
}
}
I'm writing a Sonarqube Java custom rule but keep having this error as I try to analyze my code:
"SonarQube is unable to analyze file 'File Path'
org.sonar.java.resolve.JavaSymbol$TypeJavaSymbol cannot be cast to
org.sonar.java.resolve.JavaSymbol$TypeJavaSymbol"
As you can see the original type and the casted type have the same qualified name. Therefore I assume this can only be a ClassLoader shading issue.
You can find the entire code as open-source here:
https://github.com/oasp-forge/sonarqube-devon-plugin (in case you want to check the POM or rule class).
Here is the rule code causing the issue:
package io.oasp.ide.sonarqube.common.impl;
import io.oasp.module.basic.common.api.reflect.OaspPackage;
#Rule(key = "ArchitecturePackageCheck", name = "My Package Check", description = "Verify that the code is following My package conventions.", //
priority = Priority.MAJOR, tags = { "bug" })
public class ArchitecturePackageCheck extends BaseTreeVisitor implements JavaFileScanner {
private List<String> issues;
private String fullyQualifiedName;
/**
* The constructor.
*/
public DevonArchitecturePackageCheck() {
super();
this.issues = new ArrayList<>();
}
/**
* #return fullyQualifiedName
*/
public String getFullyQualifiedName() {
return this.fullyQualifiedName;
}
#Override
public void scanFile(JavaFileScannerContext context) {
this.issues.clear();
scan(context.getTree());
for (String issue : this.issues) {
int lineNumber = 1;
context.addIssue(lineNumber, this, issue);
}
}
#Override
public void visitIdentifier(IdentifierTree tree) {
// TODO Auto-generated method stub
super.visitIdentifier(tree);
}
#Override
public void visitClass(ClassTree tree) {
this.fullyQualifiedName = ((JavaSymbol.TypeJavaSymbol) tree.symbol()).getFullyQualifiedName();
String packageName = " ";
int lastDot = this.fullyQualifiedName.lastIndexOf('.');
if (lastDot > 0) {
packageName = this.fullyQualifiedName.substring(0, lastDot);
}
if (packageName.isEmpty()) {
this.issues.add("Invalid Package IS EMPTY!" + packageName + " !");
} else {
OaspPackage pkg = OaspPackage.of(packageName);
if (!pkg.isValid()) {
this.issues.add("Invalid Package IS VALID" + packageName + " !");
}
}
}
}
Yes this is most likely related to classloader issue, you shouldn't use classes which are not exposed with the public API, i.e. anything outside the package org.sonar.plugins.java.api .
Proper way to get fully qualified name from the ClassTree is to use the Type class which can be accessed from symbol like this
classTree.symbol().type().fullyQualifiedName()
We're upgrading from Thymeleaf 2.1 to 3.0.5. Our current set up (before upgrading) has many thymeleaf templates defined and stored in a database table.
When we attempt to upgrade to 3.x our 2.1 code no longer works...ok fine but we can't find any good examples on how to do basically the same thing with Thymeleaf 3.0.5. Has anyone implemented this?
Even a decent example of how to implement org.thymeleaf.templateresolver.StringTemplateResolver would probably push us in the right direction...but we can't find anything on that either.
This is what we used in 2.1:
public class ThymeleafTemplateResolver extends TemplateResolver {
private final static String PREFIX = "";
public ThymeleafTemplateResolver() {
setResourceResolver(new DbResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
}
#Override
protected String computeResourceName(TemplateProcessingParameters params) {
String templateName = params.getTemplateName();
return templateName.substring(PREFIX.length());
}
private class DbResourceResolver implements IResourceResolver {
#Override
public InputStream getResourceAsStream(TemplateProcessingParameters params, String template) {
ThymeleafTemplateDao thymeleaftemplateDao = ApplicationContextProvider.getApplicationContext().getBean(ThymeleafTemplateDao.class);
ThymeleafTemplate thymeleafTemplate = thymeleaftemplateDao.findByTemplate(template);
if (thymeleafTemplate != null) {
return new ByteArrayInputStream(thymeleafTemplate.getContent().getBytes());
}
return null;
}
#Override
public String getName() {
return "dbResourceResolver";
}
}
}
Any help is appreciated...
Through mostly trial and error I was able to piece this together. Posting it here to help the next person looking for something similar.
This is made easier in the newer version of Thymeleaf. All one needs to do now is to extend StringTemplateResolver.
import java.util.Map;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.StringTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import com.google.common.collect.Sets;
public class ThymeleafDatabaseResourceResolver extends StringTemplateResolver {
private final static String PREFIX = "";
#Autowired ThymeleafTemplateDao thymeleaftemplateDao;
public ThymeleafDatabaseResourceResolver() {
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
}
#Override
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, Map<String, Object> templateResolutionAttributes) {
// ThymeleafTemplate is our internal object that contains the content.
// You should change this to match you're set up.
ThymeleafTemplateDao thymeleaftemplateDao = ApplicationContextProvider.getApplicationContext().getBean(ThymeleafTemplateDao.class);
ThymeleafTemplate thymeleafTemplate = thymeleaftemplateDao.findByTemplateName(template);
if (thymeleafTemplate != null) {
return super.computeTemplateResource(configuration, ownerTemplate, thymeleafTemplate.getContent(), templateResolutionAttributes);
}
return null;
}
}
I am migrating a java EE application to spring boot and i got stuck at a converting problem.
Now whether its good or not i stored my currencies as Long (its german euro).
I wrote a custom jsf converter that does something like that:
Long -> String
22 -> 00,22
3310 -> 33,10
String -> Long
3 -> 3
22,11 -> 2211
Now Spring MVC was one reason to move away from JSF.
I would like to make use of 303 Beanvalidation, with Spring MVC (#Valid #ModelAttribute, BindingResult which works fine for #Pattern e.g)
Now i cant use #NumberFormat(style=Style.Currency), which would do what I want, if I have not stored my currency as long.
I wrote a custom Formatter and registered it to FormatterRegistry
public class LongCurrencyFormatter implements Formatter<Long>{
#Getter
private static final long serialVersionUID = 1L;
#Override
public String print(Long arg0, Locale arg1) {
//logic removed for shorter post
}
#Override
public Long parse(String arg0, Locale arg1) throws ParseException {
//logic removed for shorter post
}
}
to this point everthing is working, but now every long is converted. What I think is right.
So after some research I looked into 6.6.2 Annotation-driven Formatting
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
I created as in the documentation an AnnotationFormatterFactory
public class LongCurrencyFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<LongCurrency> {
#Override
public Set<Class<?>> getFieldTypes() {
Set<Class<?>> setTypes = new HashSet<Class<?>>();
setTypes.add(Long.class);
return setTypes;
}
#Override
public Parser<?> getParser(LongCurrency annotation, Class<?> fieldType) {
return new LongCurrencyFormatter();
}
#Override
public Printer<?> getPrinter(LongCurrency annotation, Class<?> fieldType) {
return new LongCurrencyFormatter();
}
}
My annotation:
public #interface LongCurrency {
}
My Bean:
public class Costunit {
//other attributes
#LongCurrency
private long value;
}
sadly it is not working :
Failed to convert property value of type java.lang.String to required type long for property value; nested exception is java.lang.NumberFormatException: For input string: "22,00"
Sorry for the long post, any idea what i did wrong ? Or any better Solution to bind a formatter to only one controller? A Databasemirgration should be the very least option.
Thank you!
EDIT1: full Formatter code (works but could be better of course)
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
import java.util.regex.Pattern;
import lombok.Getter;
import org.springframework.format.Formatter;
public class LongCurrencyFormatter implements Formatter<Long>{
#Getter
private static final long serialVersionUID = 1L;
#Override
public String print(Long arg0, Locale arg1) {
String returnValue = arg0.toString();
boolean minusChar = returnValue.startsWith("-");
returnValue = returnValue.replace("-", "");
if (returnValue.length() > 2) {
String tempStr = returnValue.substring(0, returnValue.length()-2);
Long val = Long.parseLong(tempStr);
DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.GERMAN));
String output = df.format(val) + "," +
returnValue.substring(returnValue.length()-2);
returnValue = output;
} else {
if(returnValue.length() == 1) {
returnValue = "0,0"+returnValue;
} else {
returnValue = "0,"+returnValue;
}
}
if(minusChar) {
returnValue = "-" + returnValue;
}
return returnValue;
}
#Override
public Long parse(String arg0, Locale arg1) throws ParseException {
Long returnLong = null;
// 1Test :only one - in front, only digits and "." and one "," , and
// only 2 digits behind ","
// if "," only 2 not 1 digit behind
if (!isValidateLongCurrency(arg0)) {
returnLong = 0L;
} else {
String valueFiltered = arg0.replace(".", "");
// 2: add 2 00 if no ",":
if (!valueFiltered.contains(",")) {
valueFiltered += "00";
}
else {
//E,C or E,CC
String[] splittedValue = valueFiltered.split(",");
if(splittedValue[splittedValue.length-1].length() == 1) {
valueFiltered = valueFiltered + 0;
}
valueFiltered = valueFiltered.replace(",", "");
}
try {
returnLong = new Long(valueFiltered);
} catch (NumberFormatException numEx) {
}
}
return returnLong;
}
private boolean isValidateLongCurrency(String value) {
boolean returnValue = true;
String valueFiltered = value.replace(".", "");
//Euro
String regEx = "^-?[1-9][0-9]*(,[0-9][0-9]?)?$|^-?[0-9](,[0-9][0-9]?)?$|^$";
returnValue = Pattern.matches( regEx, valueFiltered ) ;
return returnValue;
}
}
EDIT 2, now its works
Changes made:
import java.lang.annotation.*;
#Target(value={ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
#Retention(value=RetentionPolicy.RUNTIME)
public #interface LongCurrency {
}
#Override
public void addFormatters(FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatterForFieldAnnotation(new
LongCurrencyFormatAnnotationFormatterFactory());
}
Thanks to M. Deinum
For starters your annotation isn't there anymore. You need to make sure it is retained at runtime, by default annotations are removed. For this add the #Retention meta annotation on your annotation. You probably also want to add the #Target annotation to specify on which types it can be set.
#Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface LongCurrency {}
Next make sure that you have registered your LongCurrencyFormatAnnotationFormatterFactory properly. If you don't register it it will not be used.
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new LongCurrencyFormatAnnotationFormatterFactory());
}
Both changes should make that your formatter is going to be called/used.
Let's say I have an abstract class:
abstract class Foo extends Bar {
public abstract int foo();
}
that I want to extend at runtime to create a Class object. The hope would be that I could have a dynamically generated class:
class FooImpl extends Foo {
#Override
public int foo() {
return 5;
}
}
that would be represented by a Class object and that I could then use reflection to create new instances of. The key is that I would like to decide the return value of the method foo() at runtime. My thought is to use ASM to create the bytecode for the class and then use reflection on a ClassLoader object to define the Class.
Is using ASM and then reflection of the method ClassLoader#defineClass on the generated bytes the best way to implement abstract methods at runtime with non-hardcoded values?
If yes, how would I go about doing that. My gut is to utilize the ASMifierClassVisitor, but I'm not quite sure on the exact method of doing that. I know that if all else fails I can manually go through the JVM instructions required to define a specific class but I feel there must be an easier way.
If no, what is the best way and how would I go about using the best way?
EDIT: I checked out all of the answers and I decided that none of them were exactly what I was looking for. I ended up creating a small implementation of what I was talking about with ASM. I figured I should post it here:
import org.objectweb.asm.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* Created by IntelliJ IDEA.
* User: Matt
* Date: 9/17/11
* Time: 12:42 PM
*/
public class OverrideClassAdapter extends ClassAdapter {
private final HashMap<String, Object> code;
private final String className;
private final ClassWriter writer;
private String superName;
public OverrideClassAdapter(ClassWriter writer, String className, Queue<int[]> constructorCode, HashMap<String, Object> code) {
super(writer);
this.writer = writer;
this.className = className;
this.code = code;
}
#Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.superName = name;
if((access & Opcodes.ACC_ABSTRACT) != 0)
access &= ~Opcodes.ACC_ABSTRACT;
if((access & Opcodes.ACC_INTERFACE) != 0)
access &= ~Opcodes.ACC_INTERFACE;
cv.visit(version, access, className, signature, name, null);
}
#Override
public void visitSource(String source, String debug) {
}
#Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
if(isAbstract)
access &= ~Opcodes.ACC_ABSTRACT;
MethodWriter mw = (MethodWriter) cv.visitMethod(access, name, desc, signature, exceptions);
Object value = code.get(name);
if(isAbstract || value != null) {
if(value instanceof BytecodeValue) {
BytecodeValue returnableValue = (BytecodeValue) value;
int[] byteCode = new int[returnableValue.getValueCode().length + 1];
System.arraycopy(returnableValue.getValueCode(), 0, byteCode, 0, returnableValue.getValueCode().length);
if(returnableValue.getValueCode().length > 1 && returnableValue.getValueCode()[1] == 0) {
byteCode[1] = writer.newConst(returnableValue.getValue());
}
byteCode[byteCode.length - 1] = returnableValue.getReturnCode();
value = byteCode;
}
return new OverrideMethodAdapter(mw, (int[]) value);
}
return mw;
}
private class OverrideMethodAdapter extends MethodAdapter {
private final int[] code;
private final MethodWriter writer;
public OverrideMethodAdapter(MethodWriter writer, int[] code) {
super(writer);
this.writer = writer;
this.code = code;
}
#Override
public void visitEnd() {
try {
Field code = MethodWriter.class.getDeclaredField("code");
code.setAccessible(true);
ByteVector bytes = new ByteVector();
for(int b : this.code)
bytes.putByte(b);
code.set(writer, bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static byte[] extendClassBytes(Class clazz, String className, HashMap<String, Object> methodImpls) throws IOException {
ClassReader cr = new ClassReader(clazz.getName());
ClassWriter cw = new ClassWriter(0);
cr.accept(new OverrideClassAdapter(cw, className, methodImpls), ClassReader.SKIP_DEBUG);
cr = new ClassReader(cw.toByteArray());
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
cr.accept(cw, ClassReader.SKIP_DEBUG);
//CheckClassAdapter.verify(new org.objectweb.asm.ClassReader(cw.toByteArray()), true, new PrintWriter(System.out));
/*File file = new File(className + ".class");
new FileOutputStream(file).write(cw.toByteArray());*/
return cw.toByteArray();
}
public static Class extendClass(Class clazz, String className, HashMap<String, Object> methodImpls) throws IOException {
return defineClass(extendClassBytes(clazz, className, methodImpls), className);
}
public static Class defineClass(byte[] code, String name) {
try {
Method method = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
method.setAccessible(true);
return (Class) method.invoke(Thread.currentThread().getContextClassLoader(), name, code, 0, code.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
You might want to look at using CGLib. It can do what Java's dynamic proxies can do but for abstract classes as well as interfaces, and it has a similar API to java.lang.reflect.Proxy for doing this as well. CGLib uses ASM behind the scenes anyway, but by using CGLib you wont have to craft bytecode directly.
Here's an example of how to use CGLib to do this:
package cglibtest;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibTest
{
public static void main(String... args)
{
MyAbstract instance = (MyAbstract)Enhancer.create(MyAbstract.class, new MyInterceptor(42));
System.out.println("Value from instance: " + instance.valueMethod());
}
public static class MyInterceptor implements MethodInterceptor
{
private final Object constantValue;
public MyInterceptor(Object constantValue)
{
this.constantValue = constantValue;
}
#Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable
{
if ("valueMethod".equals(method.getName()))
return(constantValue);
else
return(null);
}
}
public static abstract class MyAbstract
{
public abstract int valueMethod();
}
}
What's stopping you from reading the value 5 from say properties and return it back? That's too simple so, I guess you must have something more complex than returning an int that you want to accomplish here. I agree with the posts above that generating classes at runtime would be very expensive. If you know your business logic in advance, you can apply the Factory pattern to load the desired implementation of defined interfaces at runtime. That's how JDBC libraries work.
If you do not know the business logic in advance and have lot's of it then, you might benefit from using an off the shelf Rule Engine to process the logic and return results back to your Java program. It is much easier to maintain this logic in a Rule Engine specially if it is changing frequently.
Yes, that approach should work. But it will be expensive if you do a lot of class generation. (We are probably talking about hundreds of thousands of instructions to generate the bytecode file and then load it. And then there's the memory need to represent the class when it is loaded.)
Another approach (also expensive) is to generate source code and compile and load it at runtime.
Finally, you should consider the approach of making the logic of the objects table-driven or implementing it using some kind of interpreter. If you actually need to have different classes, you could wrap this up using Java's dynamic proxy class mechanism; e.g. see java.lang.reflect.Proxy