Prepare the Eclipse IDE for UNO

1. Prepare the Eclipse IDE

For Eclipse the necessary jar files may be made available by defining a User
Library.

Install and start Eclipse.
From the Window menu, select Preferences. On the dialog window, select Java >
Build Path > User Libraries. Press New to create a new User Library. The
library’s name might be OpenOffice.org Libraries [SDK 3.0.1]. Press OK.
Select the library and press Add JARs. On the JAR-Selection dialog you should
add the necessary libraries. For a standard installation of OpenOffice.org
3.0.1 on unix, these are
/opt/openoffice.org/ure/share/java/juh.jar
/opt/openoffice.org/ure/share/java/jurt.jar
/opt/openoffice.org/ure/share/java/ridl.jar
/opt/openoffice.org/basis3.0/program/classes/unoil.jar
Press OK to save the User Library.
Add a classpath variable. On the previous dialog window, select Java > Build
Path > Classpath Variables. Press New to create a new Variable Entry. A name
of the variable might be OO_PROGRAM. A path for a standard installation of
3.2.1 on unix is /opt/openoffice.org/program.
From the File menu, select New > Java Project. On the wizard’s page for Java
Settings select the Libraries tab. Press Add Library, select User Library and
press Next. Select the User Library you defined before and press Finish.
Continue the dialog of the New Project wizard.

A standard installation of OpenOffice.org on unix is rooted as /opt. For other
installations the libraries should be found at corresponding locations.

in my workstation:
OO_PROGRAM:
/opt/openoffice4/program
oo_classes:
/opt/openoffice4/program/classes/.jar
oo_share_classes:
/opt/oo/ure/share/java/
.jar
add classpath variable OO_PROGRAM, and user libraries oo_classes,
oo_share_classes
2. create java project
add OO_PROGRAM, oo_classes, oo_share_classes to build path
3. uno sample location:
/opt/oo/sdk/examples/DevelopersGuide/FirstSteps
4. soffice in listening mode
soffice -accept=
socket,host=localhost,port=2083;urp;StarOffice.ServiceManager

如何使用.options文件来debug Eclipse的插件

1.首先你要在你的插件根目录下,创建一个.options的文件

里面的内容如下:

com.example.youcompany.ui/debug=false

就是你的plugin名字/debug,或者任何你自己定义的debug名字。

2.在你的code中使用如下代码来做debug的输出:

private boolean isDebugEnabled() {
    if (debugEnabled == null) {
        debugEnabled = Boolean.valueOf(Platform.getDebugOption(pluginId + "/debug"));
    }
    return debugEnabled.booleanValue();
}

public logError(String errorMsg) {
    if(isDebugEnabled) {
        //process you log 
    }
}

3.然后在debug configuration的tracing tab下,enable你的debug符号,

4.Debug 就可以了。

eclipse中使用maven的两个错误

1. Maven deploy时报Fatal error compiling: tools.jar not
found错误的。原因是没有使用JDK,而使用的是JRE

在Eclipse环境下,使用Maven进行deploy时发现报了该错误:Fatal error compiling: tools.jar not
found: C:\Program Files\Java\jre6\..\lib\tools.jar.

解决办法:

点击Eclipse菜单:Window->Preferences->Java->Installed JREs,选择右侧的Edit来修改JREs,之前我的JRE
home设置的是:C:\Program Files\Jave\jre6,这个位置下是没有tools.jar包的,修改成:C:\Program
Files\Java\jdk1.6.0_25,然后点击弹出窗口的Finish按钮和主页面中的OK按钮,则问题解决

http://blog.csdn.net/achilles12345/article/details/19046061

2. 在编译包含JUnit的文件时报错,原因可能是你在JUnit的依赖中加入了test的scope,只要将它去掉就可以了。

Junit comiple failed –>remove scope item from pom.xml

编译netty的example时抛出ArtifactTransferException

ArtifactTransferException: Could not transfer artifact io.netty:netty-
tcnative:jar
You can fix them with two things:
1. Use 64-bit Windows. We do not ship the 32-bit Windows JAR with native
libraries.
2. Choose the plugin lifecycle configuration error and apply a quick fix.
Choose to ignore the offending plugin.

Java中的invokedynamic

invokedynamic字节码不能直接通过Java的编译器来直接生成的,它只有在碰到lambda的时候,会生成。

那么我们如果来测试invokedynamic字节码呢。可以通过asm-all-4.0.jar来自己生成。其实这个命名主要是为了动态语言而生的,

一般只有在写动态语言的解释器来需要用到。

可以看看下面一个例子,来了解一下invokedynamic是如何生成的使用的。

首先写一个生成invokedynamic的抽象类:

package invokedynamic;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

@SuppressWarnings("unused")
public abstract class AbstractDynamicInvokerGenerator implements Opcodes {

    public byte[] dump(String dynamicInvokerClassName, String dynamicLinkageClassName, String bootstrapMethodName, String targetMethodDescriptor)
            throws Exception {

        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, dynamicInvokerClassName, null, "java/lang/Object", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
            mv.visitCode();
            MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
                    MethodType.class);
            Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, dynamicLinkageClassName, bootstrapMethodName,
                    mt.toMethodDescriptorString());
            int maxStackSize = addMethodParameters(mv);
            mv.visitInvokeDynamicInsn("runCalculation", targetMethodDescriptor, bootstrap); //注意这里
            mv.visitInsn(RETURN);
            mv.visitMaxs(maxStackSize, 1);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

    protected abstract int addMethodParameters(MethodVisitor mv);

}

asm通过

visitInvokeDynamicInsn

命令来生成invokedynamic指令。

然后再实现一个通过invokedynamic来调用SimpleDynamicLinkageExample类bootstrapDynamic方法;

package invokedynamic.generator;

import invokedynamic.AbstractDynamicInvokerGenerator;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.objectweb.asm.MethodVisitor;

public class SimpleDynamicInvokerGenerator extends
        AbstractDynamicInvokerGenerator {

    @Override
    protected int addMethodParameters(MethodVisitor mv) {
        return 0;
    }

    public static void main(String[] args) throws IOException, Exception {
        String dynamicInvokerClassName = "invokedynamic/generator/SimpleDynamicInvoker";
        FileOutputStream fos = new FileOutputStream(new File("bin/"
                + dynamicInvokerClassName + ".class"));
        fos.write(new SimpleDynamicInvokerGenerator().dump(
                dynamicInvokerClassName,
                "invokedynamic/linkageclasses/SimpleDynamicLinkageExample",
                "bootstrapDynamic", "()V"));
    }

}

然后实现SimpleDynamicLinkageExample类:

package invokedynamic.linkageclasses;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

@SuppressWarnings({ "unused", "rawtypes" })
public class SimpleDynamicLinkageExample {

    private static MethodHandle sayHello;

    private static void sayHello() {
        System.out.println("There we go!");
    }

    public static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        Class thisClass = lookup.lookupClass(); // (who am I?)
        sayHello = lookup.findStatic(thisClass, "sayHello", MethodType.methodType(void.class));
        return new ConstantCallSite(sayHello.asType(type));
    }

}

这是需要的类就写完了,需要注意的是,你需要先在Eclipse中运行SimpleDynamicInvokerGenerator,让它生成invokedynamic/generator/SimpleDynamicInvoker.class文件;

这个类是我们的入口类,还需要注意的是,我是在Eclipse中编译这些文件的,如果你的bin目录指定到别的地方,你需要修改SimpleDynamicInvokerGenerator类中的路径;

因为生成的SimpleDynamicInvoker类对Eclipse不可见,所以我们需要在命令行中来执行它;

先cd到你的工程目录下,执行

C:\Users\tmp\workspace_java\SimpleDyn\bin>java -classpath
“C:\Users\tmp\workspace_java\SimpleDyn\bin;”
invokedynamic.generator.SimpleDynamicInvoker
There we go!

那么只是怎么完成的呢:

看看SimpleDynamicInvokerGenerator的内容就知道了:

//  (version 1.7 : 51.0, super bit)
public class invokedynamic.generator.SimpleDynamicInvoker {

  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public SimpleDynamicInvoker();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return


  // Method descriptor #10 ([Ljava/lang/String;)V
  // Stack: 0, Locals: 1
  public static void main(java.lang.String[] arg0);
    0  invokedynamic 0 runCalculation() : void [20]
    5  return

Bootstrap methods:
  0 : # 17 invokestatic invokedynamic/linkageclasses/SimpleDynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:

}

在class中JVM通过invokedynamic来调用runCalculation方法,这个方法是我们通过asm来写入的,可以是任意的名字;

然后我们用通过Bootstrap方法将runCalculation和

SimpleDynamicLinkageExample

bootstrapDynamic

方法关联起来;

SimpleDynamicLinkageExample

中我们有通过MethodHandle找到其中的sayHello方法,然后调用它,这样就完成了invokedynamic命令和实际的函数关联了起来。


http://niklasschlimm.blogspot.com/2012/02/java-7-complete-invokedynamic-
example.html

Java8的lambda(3)

lambda和匿名类

对普通的开发者来说,可以理解为lambda是匿名类的语法糖;

但是实际上不是的,lambda是通过invokedynamic来实现的,而匿名类是通过正常的产生一个类来执行的。

两者是完全不一样的。

例如:

package functional;

/*
 * Implementing the interface by creating an
 * anonymous inner class versus using 
 * lambda expression.
 */
public class SimpleFunInterfaceTest {
    public static void main(String[] args) {

        // anonymous inner class
        carryOutWork(new SimpleFuncInterface() {
            @Override
            public void doWork() {
                System.out.println("Do work in SimpleFun impl...");
            }
        });

        // lambda
        carryOutWork(() -> sleep());
    }

    private static Object sleep() {
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void carryOutWork(SimpleFuncInterface sfi) {
        sfi.doWork();
    }
}

上面这段代码一个是通过匿名类来实现,一个是通过lambda来实现,可以明显的看出lambda更加简洁;

但是两个的实现方法不一样;

匿名类会在class文件中生成一个名为SimpleFunInterfaceTest$1.class的匿名类;

而lambda会生成Bootstrap方法和lambda$0方法,然后通过invokedynamic将两者关联起来,在实际的运行过程中会生成临时的实例来调用lambda函数。