有意思的两段java代码

2020/12/06 Java 浏览

首先,创建一个实体类Order对象,代码如下:


public class Order{
        private String orderNo;
        private String name;

        public Order(){
            setOrderNo("order:"+ UUID.randomUUID().toString());
            setName("name:"+UUID.randomUUID().toString());
        }

        public String getOrderNo() {
            return orderNo;
        }

        public void setOrderNo(String orderNo) {
            this.orderNo = orderNo;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
}

第一个 方法,使用for循环遍历查找,即使找到也不做任何事,代码片段如下:


private static void test2(){
        List<Order> orderList=new ArrayList<>();
        for (int i=0;i<1000;i++){
            orderList.add(new Order());
        }
        System.out.println("aaaaa");
        boolean flag=true;
        AtomicLong atomicLong=new AtomicLong(0);
        do {
            //遍历
            for (Order order:orderList){
                if (order.getName().equals("abc")){
                    //find but do nothing
                    Optional.of(order);
                }
            }
            //orderList.stream().filter(order -> order.getName().equals("abc")).findFirst();
            long value=atomicLong.incrementAndGet();
            if (value>10000L){
                System.out.println("推出");
                flag=false;
            }
        }while (flag);
}

第二个方法,使用java8中的lambda表达式stream中的filter进行查找,代码如下:

private static void test1(){
        List<Order> orderList=new ArrayList<>();
        for (int i=0;i<1000;i++){
            orderList.add(new Order());
        }
        System.out.println("aaaaa");
        boolean flag=true;
        AtomicLong atomicLong=new AtomicLong(0);
        do {
            //遍历
            orderList.stream().filter(order -> order.getName().equals("abc")).findFirst();
            long value=atomicLong.incrementAndGet();
            if (value>10000L){
                System.out.println("推出");
                flag=false;
            }
        }while (flag);
}

两段代码如果不设置java的Xmx参数,都能正常运行,假设设置参数

java -Xmx2m

那么第二段使用java8的lambda表达式的程序将会报错,抛出异常


Exception in thread "main" java.lang.InternalError: zero_L=Lambda(a0:L)=>{
    t1:L=LambdaForm.identity_L((null));t1:L}
	at java.lang.invoke.MethodHandleStatics.newInternalError(MethodHandleStatics.java:127)
	at java.lang.invoke.LambdaForm.compileToBytecode(LambdaForm.java:660)
	at java.lang.invoke.LambdaForm.prepare(LambdaForm.java:635)
	at java.lang.invoke.MethodHandle.<init>(MethodHandle.java:461)
	at java.lang.invoke.BoundMethodHandle.<init>(BoundMethodHandle.java:58)
	at java.lang.invoke.SimpleMethodHandle.<init>(SimpleMethodHandle.java:37)
	at java.lang.invoke.SimpleMethodHandle.make(SimpleMethodHandle.java:41)
	at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1783)
	at java.lang.invoke.LambdaForm.<clinit>(LambdaForm.java:1833)
	at java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(DirectMethodHandle.java:222)
	at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:187)
	at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:176)
	at java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:83)
	at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1655)
	at java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:1612)
	at java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:1797)
	at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1746)
	at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477)
	at com.github.xiaoymin.Java8Test.test1(Java8Test.java:63)
	at com.github.xiaoymin.Java8Test.main(Java8Test.java:24)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
	at jdk.internal.org.objectweb.asm.ByteVector.<init>(ByteVector.java:84)
	at jdk.internal.org.objectweb.asm.MethodWriter.visitAnnotation(MethodWriter.java:555)
	at java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCodeBytes(InvokerBytecodeGenerator.java:640)
	at java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCode(InvokerBytecodeGenerator.java:618)
	at java.lang.invoke.LambdaForm.compileToBytecode(LambdaForm.java:654)
	... 18 more
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message can't create byte arrau at JPLISAgent.c line: 813
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message can't create byte arrau at JPLISAgent.c line: 813
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message can't create byte arrau at JPLISAgent.c line: 813

那么,是否可以认为在超过2层的for循环中,对于集合的筛选或者等其他各种操作,应该禁用java8的stream操作?

因为一旦外层for循环次数较多,java8中的stream操作将会创造很多临时对象,必然导致JVM频繁的GC操作!!

站内搜索

    Table of Contents