首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,610 阅读
2
Mac打印机设置黑白打印
4,952 阅读
3
修改elementUI中el-table树形结构图标
4,895 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,674 阅读
5
intelliJ Idea 2022.2.X破解
4,357 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Spring Cloud
Mac
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
.Net
Spring Cloud Alibaba
MySQL
Mybatis-Plus
Typecho
jQuery
Java Script
IntelliJ IDEA
微信小程序
Laughing
累计撰写
627
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
224
篇与
的结果
2021-11-14
Spring Boot使用Jetty或Undertow替换默认的Tomcat嵌入式容器
Spring Boot切换嵌入式容器的方式非常简单,只需两步,第一步排除Tomcat依赖,第二步,添加Jetty或者Undertow依赖。排除默认的Tomcat依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!--排除Tomcat--> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> 添加Jetty依赖如果使用Jetty作为嵌入式容器,我们添加如下依赖。<!--添加Jetty依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>添加Undertow依赖如果使用Undertow作为嵌入式容器,我们可以添加如下依赖<!--添加Undertow依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
2021年11月14日
986 阅读
0 评论
0 点赞
2021-11-14
java类型转换的一些问题及处理
最近在项目上被类型转换坑了不少。特以此文做一下记录。问题出在哪以前在项目开发的时候,在数据访问层,基本上是使用MyBatis,偶尔使用JPA,不管哪种方式,我们数据访问都是建立在实体之上的(极少数情况下也会使用Map,但是这种情况是比较特殊的。目前公司的开发平台,数据访问层,统一通过平台封装的BQL进行,问题就出现在这个封装的BQL上,它返回的数据类型是List<Map<String,Object>>类型,这个东西看似灵活(因为是Map,另外还是Object的泛型),既然返回的是Object类型,那就涉及到类型转换的问题。这种Object的弱类型,也给我们创建实体制作了障碍,比如我们一个实体可能有Integer类型、String类型等等。但是,我们总不能把实体全部创建层Object类型的。进一步的问题截止到目前,我们发现的第一个问题就是Object需要转换成具体的类型。紧接着,我们面临着第二个问题,就是我们通过BQL这个东西建表的时候,我们选择的比如是Integer类型(整型),我们会发现,在postgre数据库中,创建的类型确实是Integer,但是在Oracle中创建的是Number类型,然后我们在用BQL取数的时候,在postgre数据库中,取出的Object是Integer,但是在Oracle中取出的Object确实BigDecimal类型,这就让人比较懵逼了。我在创建实体的时候,到底是用Integer还是用BigDecimal呢。如何定义类型通过上面分析,我们可以确定的是,我们需要的是Integer而不是BigDecimal。所以,我们在创建实体时,创建的是一个Integer类型的。如何进行类型转换以上,便引出了我们如何进行类型转换的话题。在Java中如何进行类型转换呢,我们以Integer类型为例,常见的方式可能就以下三种。(Integer)obj:将obj转换成Integer类型,这种obj可以是Object类型。Integer.parseInt(obj):将字符串类型的obj转成对应的数值。Integer.valueOf(obj):将字符串类型的obj转成对应的数值。那么这三种方法有啥区别呢,我们以以下代码为例Object str123 = new BigDecimal("123"); int int123 = (int) str123; int parseInt = Integer.parseInt(str123.toString()); Integer valueOf = Integer.valueOf(str123.toString()); System.out.println(int123); System.out.println(parseInt); System.out.println(valueOf);以上代码,idea不会给出任何的错误提示但是我们运行时,会发现int int123 = (int) str123;这行代码会报错因为str123实际是BigDecimal类型所以(Integer)报错了。区别一:(Integer)只能转换相同的类型,否则会报错。我们跳转代码,可以查看Integer.parseInt()和Integer.valueOf()通过上面截图,我们可以看到Integer.parseInt()和Integer.valueOf()的区别。Integer.parseInt()返回的是基本类型int,Integer.valueOf()返回的是对象类型Integer。区别二:Integer.parseInt()返回的是基本类型int,Integer.valueOf()返回的是对象类型Integer。
2021年11月14日
860 阅读
0 评论
1 点赞
2021-11-13
java object转成Map
/** * object转成Map * * @param obj 对象 * @return Map */ private Map<String, Object> obj2Map(Object obj) { Map<String, Object> map = new HashMap<>(); // System.out.println(obj.getClass()); // 获取f对象对应类中的所有属性域 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { String varName = field.getName(); varName = varName.toUpperCase();//将key置为小写,默认为对象的属性 try { // 获取原来的访问控制权限 boolean accessFlag = field.isAccessible(); // 修改访问控制权限 field.setAccessible(true); // 获取在对象f中属性fields[i]对应的对象中的变量 Object o = field.get(obj); if (o != null) map.put(varName, o.toString()); // System.out.println("传入的对象中包含一个如下的变量:" + varName + " = " + o); // 恢复访问控制权限 field.setAccessible(accessFlag); } catch (IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } return map; }
2021年11月13日
1,092 阅读
0 评论
0 点赞
2021-10-23
java PreDestroy注解使用
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。比如我们可以通过此注解实现:程序停止时做一些清理工作。 @PreDestroy public void destroy(){ log.info("PreDestroy"); }当我们停止程序,会输出以下信息
2021年10月23日
924 阅读
0 评论
0 点赞
2021-10-23
Spring PostConstruct注解的使用
一、基本介绍@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。@PostConstruct在构造函数之后执行,init()方法之前执行。通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注解的方法)二、用途@PostConstruct主要用于处理一些初始化工作。比如下面代码@RestController @RequestMapping(value = "book") @Slf4j public class BookController { @Resource private IBookService bookService; /** * 构造函数 */ public BookController() { log.info("构造函数,此时bookService :" + bookService); } @PostConstruct public void init() { log.info("PostConstruct,此时bookService :" + bookService); } @GetMapping(value = "search") public List<Book> search() { return bookService.search(); } }看下控制台可以看到,构造函数里面,Bean还没有初始化,@PostConstruct里面已经完成初始化,所以,我们可以通过@PostConstruct完成一些初始化后的操作。
2021年10月23日
1,178 阅读
0 评论
0 点赞
2021-10-22
java泛型反序列化
其实不管前后端交互还有API接口,我个人更倾向于使用实体(DTO、VO)啥的,但是,有时候也不得不用Map等进行数据交互。一般而言,前后端或者接口之间交互都是通过JSON进行的,而我们在使用Map的时候,一般都是使用的泛型类,而不是使用原始类型,比如Map<String,string>,那么我们来看下下面一段代码。Map<String,String> bookMap = new HashMap<>(); bookMap.put("author","张三"); bookMap.put("name","山海经"); String bookMapString = JSONObject.toJSONString(bookMap); log.info(bookMapString);我们创建一个Map<String,String>,并将其序列化成字符串,如果我们放过来,想将字符串在反序列化成Map,我们首先想到的可能就像下面这样。Map bookMapNew = JSONObject.parseObject(bookMapString); log.info(String.valueOf(bookMapNew));程序有错吗?当然没错,但是优雅嘛,肯定是不优雅。其实这个时候,idea会给我们一个提示Raw use of parameterized class 'Map',大概意思就是说这个类要使用泛型,如果不使用泛型,我们其实丢失了类型的安全性。这个时候,我们就想到了parseObject()的重载方法,通过第二个参数,传递进去类型,如果我们是普通的类,传递一个class进去是没问题的。比如我们改写一下上面反序列化的方法Map<String,String> bookMapNew = JSONObject.parseObject(bookMapString,Map.class);这个时候,idea又会给我们一个提示大意就是类型转换没有校验。那么有没有更加完美的方法呢,有的,那就是TypeReference类,我们继续改造代码如下Map<String,String> bookMapNew = JSONObject.parseObject(bookMapString,new TypeReference<Map<String,String>>(){});这回idea终于没有提示了运行一下,结果也是正确的
2021年10月22日
1,827 阅读
0 评论
1 点赞
2021-08-30
一文撸清楚Java中的枚举enum
Java Enum类型的语法结构尽管和java类的语法不一样,应该说差别比较大。但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。定义一个枚举定义一个枚举,最简单的方式可能向下面这样public enum Size{ SMALL, MEDIUM, LARGE, EXTRA_LARGE };枚举的构造函数枚举可以定义构造函数,但是必须是private类型。public enum DishType { Fish("FISH"), Chiken("CHIKEN"), Meat("MEAT"); private String type; private DishType(String type) { this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } }你可以向上面这样添加private修饰符或者啥都不添加,但是不能添加public或protect。重写方法与类一样,可以重写枚举的方法,比如toString()方法。public enum DishType { Fish("FISH"), Chiken("CHIKEN"), Meat("MEAT"); private String type; private DishType(String type) { this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return type; } }获取枚举值可以通过.语法获取枚举值。如果想获取所有的值,可以通过values()方法 for(DishType dishType:DishType.values()){ System.out.println(dishType); }获取原始值可以通过ordinal()方法获取枚举的原始值,也就是1、2、3System.out.println(fish.ordinal());控制台输出0,因为Fish是我们在枚举值第一个定义的,从0开始。反向获取枚举可以通过valueOf()反向获取枚举值DishType.valueOf("Fish");枚举中定义方法比如在枚举中定义一个sayHello方法public void sayHello() { System.out.println("hello,i am " + type); }然后调用 DishType fish = DishType.valueOf("Fish"); fish.sayHello();枚举中的匿名内部类枚举实例后有花括号时,该枚举实例是枚举类匿名内部之类定义性别枚举类package com.company.enumpackage; public enum Gender { //枚举值调用对应构造器创建 MALE("男") { public void info() { System.out.println("这个枚举代表男"); } }, FEMALE("女") { public void info() { System.out.println("这个枚举代表女"); } }, UNKNOWN("UNKNOWN"); private final String name; //枚举类的构造器只能使用private修饰 private Gender(String name) { this.name = name; } public String getName() { return this.name; } public void info() { System.out.println("这是第一个用于定义性别的枚举类"); } }调用Gender male = Gender.MALE; Gender female = Gender.FEMALE; Gender unKnown = Gender.UNKNOWN; male.info(); female.info(); unKnown.info();
2021年08月30日
878 阅读
0 评论
24 点赞
2021-08-29
java8 Optional<T>简介
Optional<T>是Java8增加的一个用于处理NullPointException异常的类。Optional<T>是一个容器类,代表一个值存在或不存在。如果用过Spring Boot Data Jpa,会发现里面好多返回值都是Optional<T>类型的。下面我们介绍一下Optional<T>类的常见使用方法。作为演示,我们创建了一个Dish类,代码如下:public class Dish { /** * 构造函数 * @param name 名称 * @param isVegetarian 是否蔬菜 */ public Dish(String name, boolean isVegetarian) { this.name = name; this.isVegetarian = isVegetarian; } /** * 名称 */ private String name; /** * 是否蔬菜 */ private boolean isVegetarian; @Override public String toString(){ return name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isVegetarian() { return isVegetarian; } public void setVegetarian(boolean isVegetarian) { this.isVegetarian = isVegetarian; } } 创建一个Optional<T>实例创建Optional<T>实例,有两个方法,分别是of、ofNullable,ofNullable与是of的区别在于,如果传递的参数是null,那么会创建一个空的(empty)Optional<T>实例。 Optional<Dish> dishOptionalofNullable = Optional.ofNullable(null); dishOptionalofNullable.ifPresent(System.out::println); System.out.println("准备输出of方法的值"); Optional<Dish> dishOptionalof = Optional.of(null); dishOptionalof.ifPresent(System.out::println);运行代码,我们可以看到如下输出我们可以看到ofNullable创建的实例,即使传递的参数是null调用实例方法时,系统也会抛出异常,而of传递null值时,创建的Optional<T>实例也是null。判断是否为空通过isPresent()方法可以判断Optional<T>包含的类是否是null。返回true代表不是null,返回false代表是null。 Optional<Dish> emptyOptional = Optional.empty(); if (emptyOptional.isPresent()) { System.out.println(emptyOptional.get()); } else { System.out.println("empty optional"); }还有一个方法是ifPresent(Consumer<? super T> action)可以传递一个Consumer接口,当类不是null。 Optional<Dish> emptyOptional = Optional.empty(); emptyOptional.ifPresent(System.out::println);还有一个方法 ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction),当类不是null时,调用action接口,否则调用emptyAction接口。 List<Dish> menu = new ArrayList<>(); Dish fish = new Dish("鱼", false); Dish tomato = new Dish("西红柿", true); menu.add(fish); menu.add(tomato); menu.stream().filter(Dish::isVegetarian).findAny().ifPresentOrElse(System.out::println, () -> { System.out.println("没找到呢"); });获取值获取值比较简单,通过get()方法即可。 Optional<Dish> fishOptional = Optional.ofNullable(new Dish("鱼", false)); if(fishOptional.isPresent()){ System.out.println(fishOptional.get()); }通过orElse(T other)可以设置默认值。 Optional<Dish> fishOptional = Optional.ofNullable(new Dish("鱼", false)); Dish defaultDish = new Dish("default", false); if (fishOptional.isPresent()) { System.out.println(fishOptional.orElse(defaultDish)); } Optional<Dish> emptyOptional = Optional.empty(); System.out.println(emptyOptional.orElse(defaultDish));上面emptyOptional是空的,那么我们可以返回一个默认的Dish实例,下面看下控制台输出。orElse(T other)还有一些变种方法,大家可以试一下。
2021年08月29日
1,015 阅读
0 评论
0 点赞
2021-08-25
java中对象和Map的相互转换
实体对象转map集合private static Map<String, String> obj2Map(Object obj) { Map<String, String> map = new HashMap<String, String>(); // System.out.println(obj.getClass()); // 获取f对象对应类中的所有属性域 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { String varName = field.getName(); varName = varName.toLowerCase();//将key置为小写,默认为对象的属性 try { // 获取原来的访问控制权限 boolean accessFlag = field.isAccessible(); // 修改访问控制权限 field.setAccessible(true); // 获取在对象f中属性fields[i]对应的对象中的变量 Object o = field.get(obj); if (o != null) map.put(varName, o.toString()); // System.out.println("传入的对象中包含一个如下的变量:" + varName + " = " + o); // 恢复访问控制权限 field.setAccessible(accessFlag); } catch (IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } return map; }将map集合转化成实体对象利用反射实现/** * Map转成实体对象 * @param map map实体对象包含属性 * @param clazz 实体对象类型 * @return */ public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) { if (map == null) { return null; } T obj = null; try { obj = clazz.newInstance(); Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { int mod = field.getModifiers(); if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { continue; } field.setAccessible(true); field.set(obj, map.get(field.getName())); } } catch (Exception e) { e.printStackTrace(); } return obj; }
2021年08月25日
919 阅读
0 评论
0 点赞
2021-08-21
java8谓词复合和函数复合
谓词及功能复合,就是在通过组合已有的谓词或功能,形成更加复杂的谓词或功能。谓词复合谓词(Predicate)接口包含三个方法:negate、and和or,通过这三个方法,我们可以在已有谓词的基础上,组合形成更加复杂的谓词。negate代表非,and代表和,or代表或。举个例子,我们有一个苹果(Apple)类,包含颜色(color)和重量(weight)两个属性。class Apple { public Apple(String color, double weight) { this.color = color; this.weight = weight; } private String color; private double weight; @Override public String toString() { return "color:" + color + "---------" + "weight:" + weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } } 然后我们创建一个苹果的列表,存储几条测试数据。List<Apple> appleList = new ArrayList<>(); appleList.add(new Apple("red", 2)); appleList.add(new Apple("red", 6)); appleList.add(new Apple("green", 2)); appleList.add(new Apple("green", 6));negate测试我们创建一个查找红色苹果的谓词Predicate<Apple> redApple = apple -> "red".equals(apple.getColor());然后创建一个查找不是红色苹果的谓词List<Apple> notRedAppleList = appleList.stream().filter(notRedApple).collect(Collectors.toList()); for (Apple apple : notRedAppleList) { System.out.println(apple); }and测试我们首先创建一个查找重量大于5的谓词Predicate<Apple> weightThan5Apple = apple -> apple.getWeight() > 5;然后组合红苹果及重量大于5的两个谓词Predicate<Apple> redAndWeightThan5Apple = redApple.and(weightThan5Apple);测试 List<Apple> redAndWeightThan5AppleList = appleList.stream().filter(redAndWeightThan5Apple).collect(Collectors.toList()); for (Apple apple : redAndWeightThan5AppleList) { System.out.println(apple); }or测试还是利用刚才的谓词,这次我们测试重量大于5或者颜色是红色的苹果Predicate<Apple> redOrWeightThan5Apple = redApple.or(weightThan5Apple);测试 List<Apple> redOrWeightThan5AppleList = appleList.stream().filter(redOrWeightThan5Apple).collect(Collectors.toList()); for (Apple apple : redOrWeightThan5AppleList) { System.out.println(apple); }函数复合函数复合跟谓词复合类似,函数复合提供了两个接口方法:andThen和compose,通过字面含义我们可以知道andThen代表先执行第一个函数,然后在执行第二个函数,compose与之相反,先执行第二个函数,在执行第一个函数。 Function<Integer, Integer> funcPlus = x -> x + 1; Function<Integer, Integer> funcMul = y -> y * 2; Function<Integer, Integer> funcAndThen = funcPlus.andThen(funcMul); Function<Integer, Integer> funcCompose = funcPlus.compose(funcMul); System.out.println("andThen:" + funcAndThen.apply(1)); System.out.println("compose:" + funcCompose.apply(1));通过测试,我们发现andThen先执行了第一个函数,也就是1+1=2,然后执行2*2=4,所以最终结果就是4。compose限制性1*2=2,然后执行1+2=3,所以结果是3。
2021年08月21日
990 阅读
0 评论
0 点赞
2021-08-21
java8函数式接口Predicate、Consumer、Function
java8在java.util.function包中给我们预留了几个泛型函数式接口。Predicate、Consumer、Function。Predicate接口里面有一个test方法,接口一个泛型T对象并返回一个boolean值。 static <T> List<T> filter(List<T> list, Predicate<T> predicate) { List<T> result = new ArrayList<>(); for (T t : list) { if (predicate.test(t)) { result.add(t); } } return result; }传递一个String类型的列表,过滤掉其中为空的元素。 List<String> list = new ArrayList<>(); list.add(""); list.add("one"); List<String> result = filter(list,s->s.length()>0); for(String s:result){ System.out.println(s); }Consumer接口里面定义了一个accept方法,接受一个泛型T对象,没有返回值。 static <T> void consumer(List<T> list, Consumer<T> consumer) { for (T t : list) { consumer.accept(t); } }输出列表元素。 consumer(list, System.out::println);Function接口里面定义了一个apply方法,接受一个泛型T,并返回泛型R。static <T,R> List<R> func(List<T> list, Function<T,R> fun){ List<R> result = new ArrayList<>(); for(T t:list){ result.add(fun.apply(t)); } return result; }获取列表每个元素的长度。List<Integer> lengthList=func(list, String::length); for(Integer integer:lengthList){ System.out.println(integer); }
2021年08月21日
1,044 阅读
0 评论
2 点赞
2021-07-31
JVM故障诊断与性能优化之常用虚拟机参数
类加载子系统负责从文件系统或网络中加载Class信息。方法区存放类加载子系统加载的Class信息及运行时常量池信息,包括字符串的字面量和数字常量Java堆在虚拟机启动时建立,是Java程序最主要的内存工作区域,几乎所有的Java对象实例都放于Java堆中。堆空间是线程共享的。直接内存直接内存是在Java堆外直接向系统申请的内存空间,通常,访问直接内存的速度会优于Java堆。因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。直接内存在Java堆外,因此它的大小不会直接首先与Xmx指定的最大堆大小。垃圾回收系统垃圾回收器可以堆方法区、Java堆和直接内存进行回收。Java栈每个一Java虚拟机线程都有一个私有的Java栈,一个线程的Java栈在线程创建的时候被创建,Java栈中保存着局部变量、方法参数,同时和Java方法的调用、返回密切相关。本地方法栈与Java栈类似,最大的不同在于Java栈用于Java方法的调用,而本地方法栈用于本地方法的调用。作为Java虚拟机的重要扩展,Java虚拟机允许Java直接调用本地的方法(通常使用C编写)PC寄存器寄存器也是每个线程私有的空间,Java虚拟机会为每一个Java线程创建PC寄存器,在任意时刻,一个Java线程总是在执行一个方法,这个正在被执行的方法称为当前方法。如果当前方法不是本地方法,PC寄存器就会只想当前正在被执行的指令,如果当前方法是本地方法,那么PC寄存器的值就是undefined执行引擎负责执行虚拟机的字节码。常见Java虚拟机参数要诊断虚拟机,我们就要学习如何对Java虚拟机进行最基本的配置和跟踪。跟踪垃圾回收可以通过-XX:+PrintGC参数启动Java虚拟机,只要遇到GC,就会打印日志。System.out.println("##########准备申请1m内存#########"); byte[] bytes = new byte[1 * 1024 * 1024]; System.gc();GC和Full GC是垃圾回收的停顿类型,而不是区分是新生代还是年老代,如果有Full说明发生了Stop-The-World。如果是调用 System.gc()触发的,那么将显示的是Full GC (System) 4878K->1576K(249344K)表示GC 前该区域已使用容量 -> GC 后该区域已使用容量 (该区域内存总容量)0.0013118 secs表示GC所用时间,单位为秒。可以通过-XX:+PrintGCDetails参数来输出更加详细的参数。PSYoungGen:代表新生代。total 75776K, used 1951K代表新生代大小及已使用大小。[0x000000076b800000, 0x0000000770c80000, 0x00000007c0000000)代表新生代的下界、当前上界和上届。eden、from、to代表新生代的三个区,当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数-XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。ParOldGen代表老年代
2021年07月31日
609 阅读
0 评论
0 点赞
1
...
4
5
6
...
19